题意:

有一群恐怖分子要从起点st到en城市集合,你要在路程中的城市阻止他们,使得他们全部都被抓到(当然st城市,en城市也可以抓捕)。在每一个城市抓捕都有一个花费,你要找到花费最少是多少。

 

题解:

  1 //首先这一道题我原本是想这用bfs来做,因为这就相当于一棵树,你就只需要找出来怎么把它截断就可以
  2 //但是这种方法我没有尝试,我还是用的最大流。那个每一个城市可以拆点成两个,然后这两个城市之间的
  3 //权值设为这个城市的驻扎成本,然后如果两个城市相连,比如x和y相连,那么就可以建(x+n,y,INF),(y+n,x,INF)这
  4 //两条边.然后跑最大流就可以了
  5 //即使题目让你求都在哪几个点设防,你也可以写出来。因为跑完最大流之后要设防的点的流量都变成了0
  6 #include<stdio.h>
  7 #include<string.h>
  8 #include<iostream>
  9 #include<algorithm>
 10 #include<queue>
 11 using namespace std;
 12 const int maxn=1200;
 13 const int INF=0x3f3f3f3f;
 14 int head[maxn],cnt,st,en,dis[maxn],cur[maxn];
 15 struct edge
 16 {
 17     int v,next,c,flow;
 18 } e[maxn*maxn];
 19 void add_edge(int x,int y,int z)
 20 {
 21     e[cnt].v=y;
 22     e[cnt].c=z;
 23     e[cnt].flow=0;
 24     e[cnt].next=head[x];
 25     head[x]=cnt++;
 26 }
 27 bool bfs()
 28 {
 29     memset(dis,0,sizeof(dis));
 30     dis[st]=1;
 31     queue<int>r;
 32     r.push(st);
 33     while(!r.empty())
 34     {
 35         int x=r.front();
 36         r.pop();
 37         for(int i=head[x]; i!=-1; i=e[i].next)
 38         {
 39             int v=e[i].v;
 40             if(!dis[v] && e[i].c>e[i].flow)
 41             {
 42                 dis[v]=dis[x]+1;
 43                 r.push(v);
 44             }
 45         }
 46     }
 47     return dis[en];
 48 }
 49 int dinic(int s,int limit)
 50 {
 51     if(s==en || !limit) return limit;
 52     int ans=0;
 53     for(int &i=cur[s]; i!=-1; i=e[i].next)
 54     {
 55         int v=e[i].v,feed;
 56         if(dis[v]!=dis[s]+1) continue;
 57         feed=dinic(v,min(limit,e[i].c-e[i].flow));
 58         if(feed)
 59         {
 60             e[i].flow+=feed;
 61             e[i^1].flow-=feed;
 62             limit-=feed;
 63             ans+=feed;
 64             if(limit==0) break;
 65         }
 66     }
 67     if(!ans) dis[s]=-1;
 68     return ans;
 69 }
 70 int main()
 71 {
 72     int s,d,n,m;
 73     while(~scanf("%d%d",&n,&m))
 74     {
 75         scanf("%d%d",&s,&d);
 76         memset(head,-1,sizeof(head));
 77         cnt=0;
 78         int x;
 79         for(int i=1;i<=n;++i)
 80         {
 81             scanf("%d",&x);
 82             add_edge(i,i+n,x);
 83             add_edge(i+n,i,0);
 84         }
 85         st=s;
 86         en=d+n;
 87         while(m--)
 88         {
 89             int x,y;
 90             scanf("%d%d",&x,&y);
 91             add_edge(x+n,y,INF);
 92             add_edge(y,x+n,0);  //反向边也要建
 93             add_edge(y+n,x,INF);
 94             add_edge(x,y+n,0);
 95         }
 96         int ans=0;
 97         while(bfs())
 98         {
 99             for(int i=0; i<=2*n; i++)
100                 cur[i]=head[i];
101             ans+=dinic(st,INF);
102         }
103         printf("%d\n",ans);
104     }
105     return 0;
106 }