想看更多的解题报告: http://iyenn.com/rec/1824570.html
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:给你一个无向图,这个图有一个安全系数f,
f的定义是:
1.f为n,如果不管删除多少个顶点,剩下的图仍然是连通的
2.f为删除最少的顶点数,使得剩下的图不连通
给你一个图,求出f
解题思路:题目给出的目标很明显,转换成图,那么f就是无向图中的连通度吗,或者说,是求无向图中的最小割点集。
根据Menger定理,这样建图,首先将每个点拆成两个点
每个点可以表示成i与i+n
那么有向边的容量为1
如果i与j相邻,那么有有向边=
然后固定源点,枚举汇点求最大流。如果最大流都是INF,那么代表这个图是一个完全连通图,最小割点集为n
否则就输出最大流。
- /*
- Memory 272K
- Time 47MS
- */
-
- #include
- #include
- using namespace std;
- #define MAXV 110
- #define INF 1<<29
- #define min(a,b) (a>b?b:a)
-
- int map[MAXV][MAXV],flow[MAXV][MAXV];
- int parent[MAXV]; //用于bfs寻找路径
-
- int bfs(int n,int start,int end){
- int a[MAXV],i,v;
- queue <int>q;
-
- memset(a,0,sizeof(a)); //记录增广路最小流量,而且又可以当做广搜的标记数组
- memset(parent,-1,sizeof(parent)); //记录下这条增广路,以便增流
-
- q.push(start);
- a[start]=INF;
- while(!q.empty()){
- v=q.front();q.pop();
- for(i=0;i
- if(!a[i] && map[v][i]>flow[v][i]){ //如果这是一条允许弧就记录下来
- q.push(i);
- parent[i]=v;
- a[i]=min(a[v],map[v][i]-flow[v][i]);
- }
- }
- if(v==end) break; //找到增广路退出
- }
- return a[end];
- }
-
- int EdmondsKarp(int n,int sp,int fp){
- int i,tmp;
- int maxflow=0;
- memset(flow,0,sizeof(flow));
- while(tmp=bfs(n,sp,fp)){
- for(i=fp;i!=sp;i=parent[i]){ //根据父亲数组更新流量
- flow[i][parent[i]]-=tmp; //更新反向流
- flow[parent[i]][i]+=tmp; //更新正向流
- }
- maxflow+=tmp;
- }
- return maxflow;
- }
-
- int main(){
- int i,a,b;
- int n,m;
- while(~scanf("%d %d",&n,&m)){
- memset(map,0,sizeof(map));
- for(i=0;i
1; - for(i=0;i
- scanf(" (%d,%d)",&a,&b);
- map[a+n][b]=map[b+n][a]=INF;
- }
-
- int ans=INF;
- for(i=1;i
- ans=min(ans,EdmondsKarp(n*2,n,i));
- }
-
- if(ans==INF) printf("%d\n",n);
- else printf("%d\n",ans);
- }
- return 0;
- }
注:本文转载自blog.csdn.net的wangjian8006的文章"http://blog.csdn.net/wangjian8006/article/details/7988221"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
评论记录:
回复评论: