「BZOJ1834」[ZJOI2010]网络扩容

最大流费用流二合一

注意跑费用流用的图要保留跑完最大流后的反向边

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1010,M=5010,oo=2e9;
  4 int n,m,k,s,t;
  5 int level[N],edge_tot,edge_tot2;
  6 struct Edge{
  7     int from,to,flow,cap,w;
  8 }edge[M<<1],edge2[M<<2];
  9 vector<int>point[N],point2[N];
 10 void add_edge(int f,int t,int c,int ww){
 11     edge[edge_tot]=(Edge){f,t,0,c,ww};
 12     point[f].push_back(edge_tot++);
 13     return;
 14 }
 15 void add_edge2(int f,int t,int ff,int c,int ww){
 16     edge2[edge_tot2]=(Edge){f,t,ff,c,ww};
 17     point2[f].push_back(edge_tot2++);
 18     return;
 19 }
 20 bool bfs(){
 21     memset(level,0,sizeof(level));
 22     queue<int>q;
 23     q.push(s);
 24     level[s]=1;
 25     int x;
 26     while(!q.empty()){
 27         x=q.front();q.pop();
 28         for(int i=0;i<point[x].size();i++){
 29             Edge& e=edge[point[x][i]];
 30             if(e.cap<=e.flow||level[e.to]) continue;
 31             level[e.to]=level[e.from]+1;
 32             q.push(e.to);
 33         }
 34     }
 35     return level[t];
 36 }
 37 int dfs(int k,int a){
 38     if(!a||k==t) return a;
 39     int f,ans=0;
 40     for(int i=0;i<point[k].size();i++){
 41         Edge& e=edge[point[k][i]];
 42         if(e.cap<=e.flow||level[e.to]!=level[k]+1) continue;
 43         if(f=dfs(e.to,min(a,e.cap-e.flow))){
 44             a-=f,ans+=f;
 45             edge[point[k][i]].flow+=f;
 46             edge[point[k][i]^1].flow-=f;
 47             if(!a) return ans;
 48         }
 49     }
 50     return ans;
 51 }
 52 int dinic(){
 53     int ans=0;
 54     while(bfs()) 
 55         ans+=dfs(s,oo);
 56     return ans;
 57 }
 58 int dis[N],pre[N];
 59 bool inq[N];
 60 bool spfa(){
 61     queue<int>q;
 62     memset(dis,127/2,sizeof(dis));
 63     q.push(s);
 64     dis[s]=0,inq[s]=1;
 65     int x;
 66     while(!q.empty()){
 67         x=q.front();q.pop();
 68         inq[x]=0;
 69         for(int i=0;i<point2[x].size();i++){
 70             Edge& e=edge2[point2[x][i]];
 71             if(e.cap<=e.flow) continue;
 72             if(dis[e.to]>dis[x]+e.w){
 73                 dis[e.to]=dis[x]+e.w,pre[e.to]=point2[x][i];
 74                 if(!inq[e.to]){q.push(e.to);inq[e.to]=1;}
 75             }
 76         }
 77     }
 78     return dis[t]<=1e9;
 79 }
 80 int maxflowmincost(){
 81     int now,ans=0,f;
 82     while(spfa()){
 83         now=t,f=oo;
 84         while(now!=s){
 85             f=min(f,edge2[pre[now]].cap-edge2[pre[now]].flow);
 86             now=edge2[pre[now]].from;
 87         }
 88         ans+=f*dis[t],now=t;
 89         while(now!=s){
 90             edge2[pre[now]].flow+=f,edge2[pre[now]^1].flow-=f;
 91             now=edge2[pre[now]].from;
 92         }
 93     }
 94     return ans;
 95 }
 96 int main(){
 97     int t1,t2,t3,t4;
 98     scanf("%d%d%d",&n,&m,&k);
 99     for(int i=1;i<=m;i++){
100         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
101         add_edge(t1,t2,t3,t4);
102         add_edge(t2,t1,0,-t4);
103     }
104     s=1,t=n;
105     printf("%d ",dinic());
106     s=n+1;
107     add_edge2(s,1,0,k,0);add_edge2(1,s,0,0,0);
108     for(int i=0;i<m;i++){
109         Edge& e=edge[i<<1];
110         if(e.cap>e.flow){
111             add_edge2(e.from,e.to,e.flow,e.cap,0);
112         }
113         add_edge2(e.from,e.to,0,k,e.w);
114         add_edge2(e.to,e.from,0,0,-e.w);
115         e=edge[i<<1|1];
116         add_edge2(e.from,e.to,e.flow,0,0);
117     }
118     printf("%d",maxflowmincost());
119     return 0;
120 }

 

posted @ 2018-03-08 14:01  Cupcake  阅读(88)  评论(0编辑  收藏  举报