题目大意:中文题。。。
算法思路:这里明显是求最小割的。那么什么是最小割呢?最小割就是所有割的权值之和的最小值,那么什么是割呢?割就是如果把图中的一条边或几条边去掉之后使得图变得不连通。这里可以用一个叫做最大流最小割的定理:在任意一个只有一个源和一个汇的图来说,最小割就等于最大流。因此可以把问题转化为求最大流的问题。这里用ek算法求解最大流。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define MAXN 205 #define INF 0xfffffff int t; int n,m,p,a1,a2,a,b,src,sink; int maps[MAXN][MAXN],pre[MAXN]; queue<int>que; bool bfs(int s,int des) { memset(pre,-1,sizeof(pre)); while(!que.empty()) que.pop(); pre[s]=0; que.push(s); while(!que.empty()) { int index=que.front(); que.pop(); for(int i=s;i<=des;i++) { if(pre[i]==-1&&maps[index][i]>0) { pre[i]=index; if(i==des) return true; que.push(i); } } } return false; } int MaxFlow(int s,int des) { int maxflow=0; while(bfs(s,des)) { int minflow=INF; for(int i=des;i!=s;i=pre[i]) minflow=min(minflow,maps[pre[i]][i]); for(int i=des;i!=s;i=pre[i]) { maps[pre[i]][i]-=minflow; maps[i][pre[i]]+=minflow; } maxflow+=minflow; } return maxflow; } int main() { scanf("%d",&t); int sym=0; while(t--) { memset(maps,0,sizeof(maps)); sym++; scanf("%d%d%d",&n,&m,&p); src=0;sink=n; for(int i=1;i<=p;i++) { scanf("%d",&a1); maps[src][a1]=maps[a1][src]=INF; } for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); maps[a][b]=maps[b][a]=1; } printf("Case #%d: %d\n",sym,MaxFlow(src,sink)); } return 0; }