POJ - 1966 Cable TV Network (最大流求点连通度)

题意:求一个无向图的点连通度。点联通度是指,一张图最少删掉几个点使该图不连通;若本身是非连通图,则点连通度为0。
分析:无向图的点连通度可以转化为最大流解决。方法是:1.任意选择一个点作为源点;2.枚举所有与该点间没有边的点作为汇点;3.将每个点拆为入点和出点,入点到出点建一条流量为1的边;4.原本有边关系的两点,建流量为正无穷的双向边;5.每次跑出最大流,其中最小值即点连通度,若最小值为正无穷,则说明点连通度为|顶点数|。

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 1e2+5;

bool vis[maxn];
struct Edge{
    int from, to,cap,flow; 
};
struct Dinic
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init(int n){
        this->n = n;
        for(int i=0;i<=n;++i){
            G[i].clear();
        }
        edges.clear();
    }

    void AddEdge(int from,int to,int cap){
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool BFS(){
        memset(vis,0,sizeof(vis));
        queue<int> q;
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while(!q.empty()){
            int x = q.front(); q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge &e = edges[G[x][i]];
                if(!vis[e.to] && e.flow < e.cap){
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;//层次图
                    q.push(e.to);
                }
            }
        }
        return vis[t];//能否到汇点,不能就结束
    }
    int DFS(int x,int a)//x为当前节点,a为当前最小残量
    {
        if(x == t || a == 0) return a;
        int flow = 0 , r;
        for(int& i = cur[x];i < G[x].size();i++){
            Edge& e = edges[G[x][i]];
            if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 ){
                e.flow += r;
                edges[G[x][i] ^ 1].flow -= r;
                flow += r;//累加流量
                a -= r;
                if(a == 0) break;
            }
        }
        return flow;
    }
    int MaxFlow(int s,int t){
        this->s = s; this->t = t;
        int flow = 0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow += DFS(s,INF);
        }
        return flow;
    }
}F;

int G[maxn][maxn];

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N,M;
    while(scanf("%d %d",&N,&M)==2){
        int u,v,st=N;                   //任选一点为源点,此处选择0
        for(int i=0;i<N;++i){
            G[i][i] = 1;
            for(int j=i+1;j<N;++j)
                G[i][j] = G[j][i] = 0;
        }
        for(int i=1;i<=M;++i){
            scanf(" (%d,%d)",&u,&v);
            G[u][v] = G[v][u] = 1;
        }
        int ans = INF;
        for(int i=0;i<N;++i){          //枚举汇点
            if(G[0][i]) continue;
            F.init(2*N);
            for(int j=0;j<N;++j){
                F.AddEdge(j,j+N,1);     //拆点 [0,N-1]为入点,[N,2N-1]为出点
            }
            for(int j=0;j<N;++j){
                for(int k=j+1;k<N;++k){
                    if(G[j][k]){
                        F.AddEdge(j+N,k,INF);
                        F.AddEdge(k+N,j,INF);
                    }
                }
            }
            ans = min(ans,F.MaxFlow(st,i));
        }
        if(ans==INF) ans = N;
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2018-08-26 19:34  xiuwenL  阅读(243)  评论(0编辑  收藏  举报