题目大概说,一个国家有n个城市,由m条双向路相连,小偷们从城市s出发准备到h城市,警察准备在某些除了s和h外的城市布置警力抓小偷,各个城市各有警力所需的数目。问警察最少要布置多少警力才能万无一失地抓住所有小偷。
相当于就是用最小的花费让s到达不了h。这么建容量网络:
每个城市拆点连容量为需要警力数量的边,源点为s‘,汇点为h,原图双向边的容量设为INF。
最小割就是答案了。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 222 8 #define MAXM 44444 9 struct Edge{ 10 int v,cap,flow,next; 11 }edge[MAXM]; 12 int vs,vt,NV,NE,head[MAXN]; 13 void addEdge(int u,int v,int cap){ 14 edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0; 15 edge[NE].next=head[u]; head[u]=NE++; 16 edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0; 17 edge[NE].next=head[v]; head[v]=NE++; 18 } 19 int level[MAXN]; 20 int gap[MAXN]; 21 void bfs(){ 22 memset(level,-1,sizeof(level)); 23 memset(gap,0,sizeof(gap)); 24 level[vt]=0; 25 gap[level[vt]]++; 26 queue<int> que; 27 que.push(vt); 28 while(!que.empty()){ 29 int u=que.front(); que.pop(); 30 for(int i=head[u]; i!=-1; i=edge[i].next){ 31 int v=edge[i].v; 32 if(level[v]!=-1) continue; 33 level[v]=level[u]+1; 34 gap[level[v]]++; 35 que.push(v); 36 } 37 } 38 } 39 int pre[MAXN]; 40 int cur[MAXN]; 41 int ISAP(){ 42 bfs(); 43 memset(pre,-1,sizeof(pre)); 44 memcpy(cur,head,sizeof(head)); 45 int u=pre[vs]=vs,flow=0,aug=INF; 46 gap[0]=NV; 47 while(level[vs]<NV){ 48 bool flag=false; 49 for(int &i=cur[u]; i!=-1; i=edge[i].next){ 50 int v=edge[i].v; 51 if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){ 52 flag=true; 53 pre[v]=u; 54 u=v; 55 aug=min(aug,edge[i].cap-edge[i].flow); 56 if(v==vt){ 57 flow+=aug; 58 for(u=pre[v]; v!=vs; v=u,u=pre[u]){ 59 edge[cur[u]].flow+=aug; 60 edge[cur[u]^1].flow-=aug; 61 } 62 aug=INF; 63 } 64 break; 65 } 66 } 67 if(flag) continue; 68 int minlevel=NV; 69 for(int i=head[u]; i!=-1; i=edge[i].next){ 70 int v=edge[i].v; 71 if(edge[i].cap!=edge[i].flow && level[v]<minlevel){ 72 minlevel=level[v]; 73 cur[u]=i; 74 } 75 } 76 if(--gap[level[u]]==0) break; 77 level[u]=minlevel+1; 78 gap[level[u]]++; 79 u=pre[u]; 80 } 81 return flow; 82 } 83 int main(){ 84 int t,n,m,s,h,a,b; 85 scanf("%d",&t); 86 while(t--){ 87 scanf("%d%d%d%d",&n,&m,&s,&h); 88 vs=s+n; vt=h; NV=n*2+1; NE=0; 89 memset(head,-1,sizeof(head)); 90 for(int i=1; i<=n; ++i){ 91 scanf("%d",&a); 92 addEdge(i,i+n,a); 93 } 94 while(m--){ 95 scanf("%d%d",&a,&b); 96 addEdge(a+n,b,INF); 97 addEdge(b+n,a,INF); 98 } 99 printf("%d\n",ISAP()); 100 } 101 return 0; 102 }
时间: 2024-10-29 21:23:17