JZOJ 5630 Connection

Connection

Description

给定一张 N 个点M条边的连通无向图,问最少需要断开多少条边使得这张图不再连通。

Data Constraint

N <=300, M <=1000

Solution

题目要求求出无向图的最小割,我们无法知道哪一个点在 S 集,哪个在T集,我们强行规定某个点在 S 集,那么一定有一个点在T集,枚举 n -1次汇点跑网络流即可。

时间复杂度 O(?n)

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)

using namespace std;
typedef long long ll;
const ll N=500;

int f[N][N],g[N][N];
int b[N][N],gs[N],d[N];
int S,T,n,m,j,k,l,x,y;
int h[N],vh[N];

inline int min(int a,int b)
{return a<b?a:b;}

int flow(int o,int op)
{
    if(o==n)return op;
    int minh=n+1;
    fo(i,1,gs[o]){
        d[o]=d[o]==gs[o]?1:d[o]+1;
        int y=b[o][d[o]];
        if(g[o][y]){
            if(h[o]==h[y]+1){
                int zd=flow(y,min(op,g[o][y]));
                if(zd){
                    g[o][y]-=zd;
                    g[y][o]+=zd;
                    return zd;
                }
                if(h[S]>n)return 0;
            }
            minh=min(h[y]+1,minh);
        }
    }
    if(!--vh[h[o]])h[S]=n+1;
    h[o]=minh; ++vh[h[o]];
    return 0;
}

int main()
{
    cin>>n>>m; 
    fo(i,1,m){
        scanf("%d%d",&x,&y);
        ++f[x][y]; ++f[y][x];
        b[x][++gs[x]]=y; b[y][++gs[y]]=x;
    }
    int ans=m;
    fo(k,1,n-1){
        S=k;
        fo(i,1,n)fo(l,1,gs[i])g[i][b[i][l]]=f[i][b[i][l]];
        vh[0]=n; int lj=0; fo(i,1,n)vh[i]=0,h[i]=0;
        while(h[S]<=n)lj=lj+flow(S,m+1);
        ans=min(ans,lj);
    }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值