POJ1966 Cable TV Network 点连通度

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

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


而边连通度的求法:

构造一个流网络,每个无向边的容量为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。


关于点连通度和变连通度的具体定义和系统解法可以参照下面链接:

http://blog.csdn.net/bobten2008/article/details/4945141


AC代码:244K16MS

#include<iostream>
using namespace std;
#define MIN(a,b) (a<b?a:b)
const int inf=(1<<29);
const int N=105;
int n,m;
int mat[N][N];
int matinitial[N][N];
int visit[N];
int que[N];
int level[N];
bool bfs(int final)
{
    memset(level,0,sizeof(level));
    memset(visit,0,sizeof(visit));
    int head=1,tail=1;
    visit[n]=true;
    level[n]=0;
    que[tail++]=n;
    while(head<tail)
    {
        int now=que[head++];
        if(now==final)
        {
            return true;
        }
        for(int i=0;i<2*n;i++)
        {
            if(!visit[i]&&mat[now][i])
            {
                visit[i]=true;
                que[tail++]=i;
                level[i]=level[now]+1;

            }
        }
    }
    return false;
}
int dinic(int final,int now,int sum)
{
    if(now==final)
    {
        return sum;
    }
    int os=sum;
    for(int i=0;i<2*n&&sum;i++)
    {
        if(level[i]==level[now]+1&&mat[now][i])
        {
            int tmp=dinic(final,i,MIN(mat[now][i],sum));
            mat[now][i]-=tmp;
            mat[i][now]+=tmp;
            sum-=tmp;
        }
    }
    return os-sum;
}
void solve()
{
    int fmin=inf;
    int ans=0;
    for(int i=1;i<n;i++)
    {
        ans=0;
        for(int i=0;i<2*n;i++)
            for(int j=0;j<2*n;j++)
            {
                mat[i][j]=matinitial[i][j];//每次都要重新刷新一个图网络的各种参数
            }
        while(bfs(i))
        {
            ans+=dinic(i,n,inf);
        }
        if(ans<fmin)
            fmin=ans;
    }
    if(fmin>=n)
        printf("%d\n",n);
    else
        printf("%d\n",fmin);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(matinitial,0,sizeof(matinitial));
        int from,to;
        for(int i=0;i<n;i++)
        {
            matinitial[i][i+n]=1;
        }
        for(int i=1;i<=m;i++)
        {
            scanf(" (%d,%d)",&from,&to);
            matinitial[from+n][to]=inf;
            matinitial[to+n][from]=inf;
        }
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值