描述 Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求:
1、 在不扩容的情况下,1到N的最大流;
2、 将1到N的最大流增加K所需的最小扩容费用。
输入格式 Input Format
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
输出格式 Output Format
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
样例输入 Sample Input
5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
样例输出 Sample Output
13 19
时间限制 Time Limitation
1s
注释 Hint
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
来源 Source
zjoi2010
今天把oj上费用流的题写完了,真心的毒哇...........不仅建图的能力提升了,代码细节.........不说了
思路:这个题就先建将u到v的这一条边费用为0,容量为c建一条边。然后在在u到v建一条费用为W,容量为正无穷的边。然后跑一边最大流,之后再在0到1连一条容量为k费用为0的边,然后再跑一边费用流就好了。然后写完之后莫名其妙的徐王......后来发现自己又智障的打错了变量名_(:з」∠)_
代码如下:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define INF 0x7fffffff using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch>‘9‘||ch<‘0‘) { if(ch==‘-‘) f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } return x*f; } struct shadow { int y,next,v,c,rev; }a[50000]; int lin[500000],len=1,s=0,t; void insert(int x,int y,int v,int c) { a[++len].y=y;a[len].next=lin[x];a[len].v=v;lin[x]=len;a[len].rev=len+1;a[len].c=c; a[++len].y=x;a[len].next=lin[y];a[len].v=0;lin[y]=len;a[len].rev=len-1;a[len].c=-c; } int l[50000],q[50000]; int n,m,k; bool make_level() { int head=0,tail=1; memset(l,-1,sizeof(l)); q[1]=1;l[1]=0; while(head<tail) { int tn=q[++head]; for(int i=lin[tn];i;i=a[i].next) { if(a[i].v&&l[a[i].y]<0&&!a[i].c) { q[++tail]=a[i].y; l[a[i].y]=l[tn]+1; } } } return l[n]>=0; } int MAX(int k,int flow) { if(k==n) return flow; int maxflow=0,d=0; for(int i=lin[k];i&&maxflow<flow;i=a[i].next) { if(l[a[i].y]==l[k]+1&&a[i].v&&!a[i].c) { if(d=MAX(a[i].y,min(flow-maxflow,a[i].v))) { maxflow+=d; a[i].v-=d; a[a[i].rev].v+=d; } } } if(!maxflow) l[k]=-1; return maxflow; } int ans=0; void Dinic() { int d; while(make_level()) while(d=MAX(1,INF)) ans+=d; cout<<ans<<endl; } int w[50000],dis[50000],pre[50000],pro[50000]; bool vis[50000]; bool SPFA() { memset(vis,0,sizeof(vis)); memset(dis,10,sizeof(dis)); dis[s]=0;vis[s]=1;q[0]=s; int head=0,tail=1; while(head<tail) { int tn=q[head++]; vis[tn]=0; for(int i=lin[tn];i;i=a[i].next) { int tmp=a[i].y; if(dis[tn]+a[i].c<dis[tmp]&&a[i].v>0) { dis[tmp]=dis[tn]+a[i].c; if(!vis[tmp]) { vis[tmp]=1; q[tail++]=tmp; } pre[tmp]=tn; pro[tmp]=i; } } } return dis[n]!=dis[n+1]; } void agu() { int x=0x7fffffff; for(int i=n;i;i=pre[i]) x=min(x,a[pro[i]].v); for(int i=n;i;i=pre[i]) { a[pro[i]].v-=x; a[a[pro[i]].rev].v+=x; } ans+=x*dis[n]; } int Q[50000],W[50000],E[50000],R[50000]; int main() { n=read();m=read();k=read(); for(int i=1;i<=m;i++) { Q[i]=read();W[i]=read();E[i]=read();R[i]=read(); insert(Q[i],W[i],E[i],0); insert(Q[i],W[i],INF,R[i]); } Dinic(); insert(0,1,k,0); ans=0; while(SPFA()) agu(); cout<<ans<<endl; return 0; }
(=´ω`=)
时间: 2024-10-17 08:21:50