bzoj1834
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 3382 Solved: 1768
[Submit][Status][Discuss]
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
Output
输出文件一行包含两个整数,分别表示问题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
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
第一问:按题目要求建费用为0的边,跑一次最大流
第二问:新建原点S,S->1费用0容量K,对于每一条原图边u->v,新建一条u->v费用w容量inf的边
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> #define ll long long #define N 5005 using namespace std; int n,m,k,hd[N],vis[N],d[N],cur[N],w[N<<2],pre[N<<2],a[N<<2],tot=1,ans,flow,cost; struct edge{int u,v,next,w,cap,flow;}e[N<<2]; void adde(int u,int b,int c,int d){ e[++tot].v=b;e[tot].u=u;e[tot].next=hd[u]; e[tot].cap=c;e[tot].w=d;e[tot].flow=0;hd[u]=tot; } queue<int>q; bool bfs(){ memset(vis,0,sizeof(vis)); q.push(1);d[1]=0;vis[1]=1; while(!q.empty()){ int u=q.front();q.pop(); for(int i=hd[u];i;i=e[i].next){ int v=e[i].v; if(!vis[v]&&e[i].cap>e[i].flow){ vis[v]=1; d[v]=d[u]+1; q.push(v); } } } return vis[n]; } int dfs(int u,int a){ if(u==n||!a)return a; int flow=0,f; for(int& i=cur[u];i;i=e[i].next){ int v=e[i].v; if(d[u]+1==d[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){ e[i].flow+=f; e[i^1].flow-=f; flow+=f;a-=f; if(!a)break; } } return flow; } bool spfa(int s,int t,int &flow,int &cost){ for(int i=1;i<=t;i++)d[i]=0x3f3f3f3f; memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); q.push(s);vis[s]=1;a[s]=0x3f3f3f3f;d[s]=0; while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; for(int i=hd[u];i;i=e[i].next){ int v=e[i].v; if(e[i].cap>e[i].flow&&d[v]>d[u]+e[i].w){ d[v]=d[u]+e[i].w; pre[v]=i; a[v]=min(e[i].cap-e[i].flow,a[u]); if(!vis[v]){ q.push(v); vis[v]=1; } } } } if(d[t]==0x3f3f3f3f)return 0; flow+=a[t];cost+=d[t]*a[t]; int u=t; while(u!=s){ e[pre[u]].flow+=a[t]; e[pre[u]^1].flow-=a[t]; u=e[pre[u]].u; } return 1; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++){ int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); adde(a,b,c,0);w[tot]=d; adde(b,a,0,0);w[tot]=d; } while(bfs()){ for(int i=1;i<=n;i++)cur[i]=hd[i]; ans+=dfs(1,0x3f3f3f3f); } int cnt=tot; for(int i=2;i<=cnt;i++){ int u=e[i].u,v=e[i].v; if(e[i].cap>0)adde(u,v,0x3f3f3f3f,w[i]); else adde(u,v,0,w[i]); }adde(n,n+1,k,0); while(spfa(1,n+1,flow,cost)); printf("%d %d",ans,cost); return 0; }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。