网络流杂题

UVA1660 电视网络 Cable TV Network
链接
题目大意: 给定一个n(n <= 50)个点的无向图,求它的点联通度。即最少删除多少个点,使得图不连通。

无向图 最小割点 先拆点 枚举s,t跑dinic s,t拆点连INF 其他点拆点连1

#include 
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 200;
const int maxm = 2e4+100;
int n, m;
int to[maxm], nxt[maxm], w[maxm];
int fst[maxn], cnt, cur[maxn];
int s, t, d[maxn];
int a[maxn*maxn],b[maxn*maxn];

void init() {
    memset(fst, -1, sizeof(fst));
    cnt = 0;
}

void addedge(int u, int v, int val) {
    to[cnt] = v;
    w[cnt] = val;
    nxt[cnt] = fst[u];
    fst[u] = cnt++;

    to[cnt] = u;
    w[cnt] = 0;
    nxt[cnt] = fst[v];
    fst[v] = cnt++;
}

int bfs() {
    queue<int> Q;
    memset(d, 0, sizeof(d));
    d[s] = 1;
    Q.push(s);
    while (!Q.empty()) {
        int u = Q.front();
        Q.pop();
        for (int i = fst[u]; ~i; i = nxt[i]) {//因为初始是-1
            int v = to[i];
            if (w[i] > 0 && d[v] == 0) {
                d[v] = d[u] + 1;
                if (v == t) return 1;
                Q.push(v);
            }

        }
    }
    return d[t] != 0;
}
inline int read(){
    int x=0,f = 1;
    char ch = '{';
    while (ch<'0' || ch>'9'){ch = getchar();if (ch == '-')f = -1;}
    while (ch>='0' && ch<='9'){x = x*10+ch-'0';ch = getchar();}
    return x*f;
}

int dfs(int u, int flow) {
    if (u == t)
        return flow;
    int ans = 0, x = 0;
    for (int i = cur[u]; ~i; i = nxt[i]) {
        int v = to[i];
        if (w[i]>0 && d[v] == d[u]+1){
            x = dfs(v,min(flow-ans,w[i]));
            w[i]-=x;
            w[i^1]+=x;
            if (w[i]) cur[u] = i;
            ans+=x;
            if (ans == flow) return flow;
        }
    }
    if (ans == 0)d[u] =0;
    return ans;
}

int dinic(int n){ // n:total
    int ans = 0;

    while (bfs()){
        for (int i=1;i<=n;i++)
            cur[i]  = fst[i];
        ans+=dfs(s,INF);
    }
    return ans;
}
int main() {
//    ios::sync_with_stdio(false);
//    cin.tie(0);
//    cout.tie(0);

    while (scanf("%d%d",&n,&m)!=EOF){
        memset(a,0, sizeof(a));
        memset(b,0, sizeof(b));
        for (int i= 1;i<=m;i++){
            a[i] = read()+1;
            b[i] = read()+1;
        }

        int ans = INF;
        for (s = 1;s<=n;s++)
            for (t=1;t<=n;t++)
                if (s!=t){
                    init();
                    int res = 0;
                    for (int i =1;i<=n;i++)
                        if (i==s || i==t) addedge(i,i+n,INF);
                        else addedge(i,i+n,1);
                    for (int i=1;i<=m;i++){
                        addedge(a[i]+n,b[i],INF);
                        addedge(b[i]+n,a[i],INF);
                    }
                    ans = min(ans,dinic(n*2));
                }
        if (n<=1 || ans == INF) ans = n;
        printf("%d\n",ans);
    }

}

你可能感兴趣的:(网络流杂题)