1 条题解
-
0
自动搬运
来自洛谷,原作者为

听取MLE声一片
如果我当时做的再多一点,结局会不会不同呢?搬运于
2025-08-24 21:13:52,当前版本为作者最后更新于2021-07-30 19:13:23,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这道题对
EK+spfa算法不太友好,需要卡常才能通过。(但是好歹卡过去了)
学习费用流(最小费用最大流)首先要学习网络流,可以看我的题解,当然可以参考经典日报。
费用流和网络流的形态很类似,主体还是根据网络流。下面举一个例子(又是借鉴日报)。
假设
s城有inf个(穷)人想去t城,但是从s到t要经过一些城市才能到达,每条路有最大流量和权值(流量通过1所花费的代价),问最终最多能有多少人能到达t城。(由于是穷人)他们希望能在最多人到达t城的同时花最少的钱,问最少的钱是多少。费用流就是在流量最大的情况下所花费的最小费用。
相较于网络流,费用流只是增加了权值,我们只需要解决权值问题即可。
这你想到了什么?代价最小?那就最短路!
因为有负权边,所以
spfa是最方便的!而且需要进行多次spfa所以基本上不会全都卡成 。关于
spfa它诈尸了!(大雾)再详细一点,就是把
bfs改成spfa,再松弛过程中记录路径即可。这道板子题会卡一下
EK+SPFA,所以需要进行卡常。下面是代码:
#include<iostream> #include<cstdio> #include<cmath> #include<string> #include<cstring> #include<algorithm> using namespace std; namespace in{ #ifdef faster char buf[1<<21],*p1=buf,*p2=buf; inline int getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} #else inline int getc(){return getchar();} #endif template <typename T>inline void read(T& t){ t=0;int f=0;char ch=getc();while (!isdigit(ch)){if(ch=='-')f = 1;ch=getc();} while(isdigit(ch)){t=t*10+ch-48;ch = getc();}if(f)t=-t; } template <typename T,typename... Args> inline void read(T& t, Args&... args){read(t);read(args...);} } namespace out{ char buffer[1<<21];int p1=-1;const int p2 = (1<<21)-1; inline void flush(){fwrite(buffer,1,p1+1,stdout),p1=-1;} inline void putc(const char &x) {if(p1==p2)flush();buffer[++p1]=x;} template <typename T>void write(T x) { static char buf[15];static int len=-1;if(x>=0){do{buf[++len]=x%10+48,x/=10;}while (x);}else{putc('-');do {buf[++len]=-(x%10)+48,x/=10;}while(x);} while (len>=0)putc(buf[len]),--len; } } const int inf=2147483647; int maxn,cost; int top=1,head[5001]; int dis[5001]; int n,m,s,t,book[5001]; int min(int a,int b){ return a>b?b:a; } struct point{ int v,w,val,next; }a[100001]; struct b{ int fa; int v; }b[5001]; inline void add(int u,int v,int val,int w){ a[++top].v=v; a[top].val=val; a[top].w=w; a[top].next=head[u]; head[u]=top; } queue<int> q; inline bool spfa(){ for(register int i=1;i<=n;i++) dis[i]=inf,b[i].fa=b[i].v=book[i]=0; dis[s]=0; q.push(s); book[s]=1; while(!q.empty()){ int u=q.front(); book[u]=0; q.pop(); for(register int i=head[u];i;i=a[i].next){ int v=a[i].v,w=a[i].w; if(a[i].val>0&&dis[v]>dis[u]+w){ dis[v]=dis[u]+w; b[v].fa=u,b[v].v=i; if(book[v]==0){ q.push(v); book[v]=1; } } } } return dis[t]!=inf; } void EK(){ while(spfa()){ int minn=inf; for(register int i=t;i!=s;i=b[i].fa) minn=min(minn,a[b[i].v].val); for(register int i=t;i!=s;i=b[i].fa){ a[b[i].v].val-=minn; a[b[i].v^1].val+=minn; } maxn+=minn; cost+=minn*dis[t]; } return; } int main() { in::read(n,m); s=1,t=n; int u,v,val,w; for(register int i=1;i<=m;i++){ in::read(u,v,val,w); add(u,v,val,w); add(v,u,0,-w); } EK(); printf("%d %d",maxn,cost); return 0; }
- 1
信息
- ID
- 6858
- 时间
- 1500ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- (无)
- 递交数
- 0
- 已通过
- 0
- 上传者