poj1966求顶点连通度

来源:互联网 发布:加强网络市场监管 编辑:程序博客网 时间:2024/05/18 07:00


题目连接



顾名思义。点连通度即使在一个图中,去掉多少个点可以使这个图不连通。

因为点连通度的求法是构图时转化为边连通度来求的。


而边连通度的求法:

构造一个流网络,每个无向边的容量为1。

任意取一个点作为源点。

枚举剩下的店作为汇点,求最小割。

枚举完取最小割最小的值就是ans。

(我的理解其实就是整体的边连通度是取决于“最短板”,即存在的两个点间连通强度最弱。)

(而刚好最小割其实就是流网络流求最大流时的“最短板”,故此时边连通度突然和最小割连通起来也不是那么不可思议了吧)


构图:(拆点)

(1) 原 G 图中的每个顶点 v 变成 N 网中的两个顶点 v' 和 v" ,顶点 v' 至 v" 有一条弧(有向边)连接,弧容量为 1; 
(2) 原 G 图中的每条边  e = uv ,在 N 网中有两条弧 e’= u"v',e"=v"u' 与之对应, e' 弧容量为 ∞ ,  e" 弧容量为 ∞ 。

(3)A” 为源顶点, B' 为汇顶点 

解法:

任意取一个点作为源点,枚举其他汇点(注意,比如取v1''作为源点,则其他汇点不包括v1')。

然后最大流最小割,取最小的最小割。

当fmin>=n(因为有可能fmin==无穷大),则ans=n。


#include<cstdio>#include<cstring>#include<iostream>using namespace std;#define maxn 110#define INF 0xfffffffint map[maxn][maxn];// 矩阵  dinicint N;int flow[maxn][maxn];int level[maxn];bool make_level(int s,int t){    memset(level,0,sizeof(level));    level[s]=1;    int que[maxn];    int front=0,rear=0;    que[rear++]=s;    while(front<rear){        int top=que[front++];        if(top==t) return true;        for(int i=0;i<N;++i){            if(!level[i]&&flow[top][i]){                que[rear++]=i;                level[i]=level[top]+1;            }        }    }    return false;}int DFS(int now,int maxf,int t){    if(now==t) return maxf;    int ret=0,ans;    int k;    for(int k=0;k<N;k++){        if((flow[now][k])&&(level[k]==(level[now]+1))){            ans=DFS(k,min(maxf-ret,flow[now][k]),t);            flow[now][k]-=ans;            flow[k][now]+=ans;            ret+=ans;            if(ret==maxf) return ret;        }    }    return ret;}int dinic(int s,int t){    int ans=0;    while(make_level(s,t)) ans+=DFS(s,INF,t);    return ans;}int n,m;int main(){    while(~scanf("%d%d",&n,&m)){        char ch[10];        N=2*n;        int a,b;        memset(map,0,sizeof(map));        for(int i=0;i<N;++i) map[i][i+n]=1;        for(int i=0;i<m;++i){            scanf("%s",ch);            sscanf(ch,"(%d,%d)",&a,&b);            map[a+n][b]=map[b+n][a]=INF;        }        for(int i=0;i<N;++i){            for(int j=0;j<N;++j) cout<<map[i][j]<<" ";            cout<<endl;        }        int ans=INF;        for(int i=1;i<n;++i){            memcpy(flow,map,sizeof(map));            int p=dinic(n,i);            ans=min(ans,p);        }        if(ans==INF) ans=n;        printf("%d\n",ans);    }    return 0;}