HDU 4289 Control [网络流拆点]

  图上的每个点有权值,求使从起点无法到达终点去掉的权值和最小。

  因为权值在点上,所以要进行拆点。将i点拆为2i和2i+1。然后流量统一从偶数点进,奇数点出,点之间连流量为点权的有向边,无向边拆成两条有向边,分别向两个端点连两条流量为无穷大的有向边,如下图所示。

 1 #include <string.h>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #define MAXN 500
 5 #define MAXE 100000
 6 #define INF 0x3f3f3f3f
 7 struct edge{
 8     int v,e,n,flow;
 9 }e[MAXE];
10 int first[MAXN],es;
11 int work[MAXN],q[MAXN],d[MAXN],front,rear;
12 void addedge(int u,int v,int flow){
13     e[es].v=v,e[es].flow=flow,e[es].n=first[u],first[u]=es++;
14 }
15 int bfs(int s,int t,int n){
16     memset(d,-1,sizeof(d[0])*(n+1));
17     q[front=rear=d[s]=0]=s,rear++;
18     while(front<rear){
19         int u=q[front++];
20         for(int i=first[u];i!=-1;i=e[i].n)
21             if(e[i].flow&&d[e[i].v]==-1){
22                 d[e[i].v]=d[u]+1,q[rear++]=e[i].v;
23                 if(e[i].v==t)return 1;
24             }
25     }
26     return 0;
27 }
28 int dfs(int cur,int t,int res){
29     if(cur==t)return res;
30     for(int &i=work[cur];i!=-1;i=e[i].n)
31         if(e[i].flow&&d[e[i].v]==d[cur]+1)
32             if(int tmp=dfs(e[i].v,t,std::min(res,e[i].flow))){
33                 e[i].flow-=tmp,e[i^1].flow+=tmp;
34                 return tmp;
35             }
36     return 0;
37 }
38 int dinic(int s,int t,int n){
39     int ans=0,tt;
40     while(bfs(s,t,n)){
41         memcpy(work,first,sizeof(first[0])*(n+1));
42         while(tt=dfs(s,t,INF))ans+=tt;
43     }
44     return ans;
45 }
46 int n,m,s,t,ci,tu,tv,va;
47 int main(){
48     //freopen("test.in","r",stdin);
49     while(scanf("%d%d",&n,&m)!=EOF){
50         scanf("%d%d",&s,&t);
51         int va=INF;
52         memset(first,-1,sizeof first);es=0;
53         for(int i=1;i<=n;i++){
54             scanf("%d",&ci);
55             addedge(i<<1,i<<1|1,ci);
56             addedge(i<<1|1,i<<1,0);
57             if(i==s||i==t)va=std::min(va,ci);
58         }
59         s=s<<1,t=t<<1|1;
60         for(int i=0;i<m;i++){
61             scanf("%d%d",&tu,&tv);
62             addedge(tu<<1,tv<<1|1,0);
63             addedge(tv<<1|1,tu<<1,INF);
64             addedge(tv<<1,tu<<1|1,0);
65             addedge(tu<<1|1,tv<<1,INF);
66         }
67         printf("%d\n",std::min(va,dinic(s,t,2*n+2)));
68     }
69 
70     return 0;
71 }
原文地址:https://www.cnblogs.com/swm8023/p/2694594.html