【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容

【题目大意】

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

【思路】

问题用Dinic搞一搞。问题二可以看出是费用流。

(1)残余网络中边还有一些容量,而如果利用这些容量,是不需要花费新的费用的。则将这些边的费用设置为0。

(2)对于原有的边,添加一条起点、终点相同的点,容量设置为INF,费用设置为一开始输入的扩容费用。再添加一个超级源点,和1之间添加一条边,容量为K,费用为0。

所谓的费用流,就是将EK中每一次搜索改为关于单位费用的SPFA即可,其余板块类似。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue> 
  7 using namespace std;
  8 const int MAXN=1000+50;
  9 const int MAXM=5000+50;
 10 const int INF=0x7fffffff;
 11 int n,m,k;//点数边数和需要扩充的容量 
 12 struct node
 13 {
 14     int to,cap,pos,w;
 15 };
 16 vector<node> E[MAXN];
 17 int vis[MAXN];
 18 int dis[MAXN];
 19 int U[MAXM],V[MAXM],C[MAXM],W[MAXM];
 20 int pre[MAXN],preedge[MAXN];//记录每次SPFA中每一个节点的前驱,以及当前节点在前驱的vector中是第几条边 
 21 
 22 void addedge(int u,int v,int c,int w)
 23 {
 24     E[u].push_back((node){v,c,E[v].size(),w});
 25     E[v].push_back((node){u,0,E[u].size()-1,-w});/*失误把这里敲成了E[u],看了好久才看出来T T*/ 
 26 }
 27 
 28 void init()
 29 {
 30     scanf("%d%d%d",&n,&m,&k);
 31     for (int i=0;i<m;i++)
 32     {
 33         scanf("%d%d%d%d",&U[i],&V[i],&C[i],&W[i]);
 34         addedge(U[i],V[i],C[i],0);
 35     }
 36 }
 37 
 38 int bfs()
 39 {
 40     queue<int> que;
 41     memset(dis,-1,sizeof(dis));
 42     dis[1]=0;
 43     que.push(1);
 44     while (!que.empty())
 45     {
 46         int head=que.front();que.pop();
 47         for (int i=0;i<E[head].size();i++)
 48         {
 49             node tmp=E[head][i];
 50             if (dis[tmp.to]==-1 && tmp.cap>0)
 51             {
 52                 dis[tmp.to]=dis[head]+1;
 53                 que.push(tmp.to);
 54             }
 55         } 
 56     }
 57     if (dis[n]==-1) return 0;
 58         else return 1;
 59 }
 60 
 61 int dfs(int s,int e,int f)
 62 {
 63     vis[s]=1;
 64     if (s==e) return f;
 65     for (int i=0;i<E[s].size();i++)
 66     {
 67         node& tmp=E[s][i];
 68         if (!vis[tmp.to] && tmp.cap>0 && dis[tmp.to]==dis[s]+1)
 69         {
 70             int delta=dfs(tmp.to,e,min(f,tmp.cap));
 71             if (delta>0)
 72             {
 73                 tmp.cap-=delta;
 74                 E[tmp.to][tmp.pos].cap+=delta;
 75                 return delta;
 76             }
 77         }
 78     }
 79     return 0;
 80 }
 81 
 82 void dinic()
 83 {
 84     int flow=0;
 85     while (bfs())
 86     {
 87         memset(vis,0,sizeof(vis));
 88         int f=dfs(1,n,INF);
 89         if (f==0) break;
 90             else flow+=f;
 91     }
 92     cout<<flow<<' '; 
 93 }
 94 
 95 void rebuild()
 96 {
 97     for (int i=0;i<m;i++) addedge(U[i],V[i],INF,W[i]);
 98     addedge(0,1,k,0);
 99 }
100 
101 int spfa(int u,int v)
102 {
103     memset(vis,0,sizeof(vis));
104     for (int i=0;i<=n;i++) dis[i]=INF;
105     memset(pre,-1,sizeof(pre));
106     queue<int> que;
107     dis[0]=0;
108     vis[0]=1;
109     que.push(0);
110     while (!que.empty())
111     {
112         int head=que.front();
113         que.pop();
114         vis[head]=0;
115         for (int i=0;i<E[head].size();i++)
116         {
117             node& tmp=E[head][i];
118             if (tmp.cap>0 && dis[tmp.to]>dis[head]+tmp.w)
119             {
120                 dis[tmp.to]=dis[head]+tmp.w;
121                 pre[tmp.to]=head;
122                 preedge[tmp.to]=i;
123                 if (!vis[tmp.to])
124                 {
125                     vis[tmp.to]=1;
126                     que.push(tmp.to);
127                 }
128             }
129         }
130     }
131     if (dis[n]==INF) return 0;
132     else return 1;
133 }
134 
135 void mcf()
136 {
137     int ans=0;
138     while (spfa(1,n))
139     {
140         int flow=INF;
141         for (int i=n;pre[i]!=-1;i=pre[i])
142             flow=min(flow,E[pre[i]][preedge[i]].cap);
143         for (int i=n;pre[i]!=-1;i=pre[i])
144         {
145             node& tmp=E[pre[i]][preedge[i]];
146             tmp.cap-=flow;
147             E[tmp.to][tmp.pos].cap+=flow;
148             ans+=flow*tmp.w;
149         }
150     }
151     cout<<ans<<endl; 
152 }
153 
154 int main()
155 {
156     init();
157     dinic();
158     rebuild(); 
159     mcf();
160     return 0;
161 } 

 

你可能感兴趣的:(【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容)