题意:有N个城市,现在城市S出现了一伙歹徒,他们想运送一些炸弹到D城市,不过警方已经得到了线报知道他们的事情,不过警察不知道他们所在的具体位置,所以只能采取封锁城市的办法来阻断暴徒,不过封锁城市是需要花费一定代价的,由于警局资金比较紧张,所以想知道如果完全阻断暴徒从S城市到达D城市的最小需要花费的代价。
思路:将每个点都拆分成2个,表示为i和i*,i是原来的起点,然后i到i*的权值为i点原来的权值,连边的时候要注意的是要从i*连接i,因为最初在起点的时候,首先要走的就是从i到i*,然后接下来一定是从i*出发回到i这一边,假设是j,然后j走j*,这样循环往复,所以边的方向都应该是i*到i。
1 #include<cstdio> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 #include<queue> 6 using namespace std; 7 const int maxn=1000; 8 const int inf=0x3f3f3f3f; 9 int head[maxn],level[maxn]; 10 int num; 11 void init() 12 { 13 num=-1 ; 14 memset(head,-1,sizeof(head)); 15 } 16 struct node 17 { 18 int v,w,next; 19 }G[400000]; 20 int bfs(int s,int t) 21 { 22 queue<int>q; 23 q.push(s); 24 memset(level,-1,sizeof(level)); 25 level[s]=0; 26 while(!q.empty()){ 27 int u=q.front(); 28 q.pop(); 29 for(int i=head[u];i!=-1;i=G[i].next){ 30 int v=G[i].v; 31 if(G[i].w>0&&level[v]==-1){ 32 level[v]=level[u]+1; 33 q.push(v); 34 } 35 } 36 } 37 return level[t]; 38 } 39 int dfs(int s,int t,int f) 40 { 41 if(s==t) return f; 42 int ans=0; 43 for(int i=head[s];i!=-1;i=G[i].next){ 44 int v=G[i].v; 45 if(G[i].w>0&&level[s]+1==level[v]){ 46 int d=dfs(v,t,min(G[i].w,f-ans)); 47 if(d>0){ 48 G[i].w-=d; 49 G[i^1].w+=d; 50 ans+=d; 51 if(ans==f) return ans; 52 } 53 } 54 } 55 return ans; 56 } 57 int dinic(int s,int t) 58 { 59 int ans=0; 60 while(1){ 61 int temp=bfs(s,t); 62 if(temp==-1) break; 63 ans+=dfs(s,t,inf); 64 } 65 return ans; 66 } 67 void build(int u,int v,int w) 68 { 69 num++; 70 G[num].v=v; 71 G[num].w=w; 72 G[num].next=head[u]; 73 head[u]=num; 74 75 num++; 76 G[num].v=u; 77 G[num].w=0; 78 G[num].next=head[v]; 79 head[v]=num; 80 } 81 int main() 82 { 83 int n,m; 84 while(scanf("%d%d",&n,&m)!=EOF){ 85 init(); 86 int s,t; 87 scanf("%d%d",&s,&t); 88 t=t+n; 89 int temp; 90 for(int i=1;i<=n;i++){ 91 scanf("%d",&temp); 92 build(i,i+n,temp); 93 } 94 for(int i=1;i<=m;i++){ 95 int u;int v; 96 scanf("%d%d",&u,&v); 97 build(u+n,v,inf); 98 build(v+n,u,inf); 99 } 100 printf("%d\n",dinic(s,t)); 101 } 102 return 0; 103 }