zoukankan      html  css  js  c++  java
  • POJ 1966 Cable TV Network (点连通度)【最小割】

    <题目链接>

    题目大意:

    给定一个无向图,求点连通度,即最少去掉多少个点使得图不连通。

    解题分析:

    解决点连通度和边连通度的一类方法总结见   >>>

    本题是求点连通度,所以对每个点进行拆点,然后入点向出点连一条容量为1的边,其它边则是用一个容量为INF的边来代替。然后就是枚举一下源点和汇点,跑最大流,选最小的值即可。不过,本题需要注意一下是否为完全图,因为完全图的最大流是INF,所以特判一下,如果是完全图,就将点全部删除,输出n。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstring>
    using namespace std;
    
    typedef long long ll;
    const int N = 500 , INF = 0x3f3f3f3f;
    
    struct Dinic
    {
        struct edge{ int from,to;ll cap,flow; };     //cap-flow才是这条边的真实流量
        vector<edge>es;
        vector<int>G[N];
        bool vis[N];
        int dist[N],iter[N];
        void init(int n){
            for(int i=0; i<=n+10; i++)G[i].clear();
            es.clear();
        }
        void addedge(int from,int to,ll cap){
            es.push_back((edge){from,to,cap,0});    //将边存储的边表
            es.push_back((edge){to,from,0,0});
            int x=es.size();     
            G[from].push_back(x-2);    //G[u][i]记录以u为顶点的第i条边的反边在es中的编号
            G[to].push_back(x-1);
        }
        bool BFS(int s,int t){      //bfs将该图划分成分层图
            memset(vis,0,sizeof(vis));
            queue <int> q;
            vis[s]=1;
            dist[s]=0;
            q.push(s);
            while(!q.empty()){
                int u=q.front();q.pop();
                for(int i=0; i<G[u].size(); i++){
                    edge &e=es[G[u][i]];
                    if(!vis[e.to]&&e.cap>e.flow){
                        vis[e.to]=1;
                        dist[e.to]=dist[u]+1;
                        q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        int DFS(int u,int t,ll f){
            if(u==t||f==0)return f;
            int nowflow=0,d;
            for(int &i=iter[u]; i<G[u].size(); i++){
                edge &e=es[G[u][i]];
                if(dist[u]+1==dist[e.to]&&(d=DFS(e.to,t,min(f,e.cap-e.flow)))>0){
                    e.flow+=d;     //正边真实流量-d
                    es[G[u][i]^1].flow-=d;    //反边真实流量+d
                    nowflow+=d;    //得到现在搜得的能够流入汇点的流量
                    f-=d;      //找到一条增广路之后,减去这条路的流量,然后继续从这个顶点的其它边开始寻找增广路
                    if(f==0)break;
                }
            }
            return nowflow;
        }
        int Maxflow(int s,int t){
            int flow=0;
            while(BFS(s,t)){
                memset(iter,0,sizeof(iter));
                int d=0;
                while(d=DFS(s,t,INF))flow+=d;
            }
            return flow;
        }
    }dinic;
    
    
    int mpa[110][110];
    int n,m;
    
    inline void getGraph(){
        dinic.init(2*n+5);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)dinic.addedge(i,i+n,1);
                else if(mpa[i][j])dinic.addedge(i+n,j,INF);
            }
        }
    }
    
    int main(){
        while(cin>>n>>m){
            memset(mpa,0,sizeof(mpa));
            for(int i=1;i<=m;i++){
                int u,v;scanf(" (%d,%d)",&u,&v);
                mpa[u][v]=mpa[v][u]=1;
            }
            int ans=INF;
            for(int st=0;st<n;st++){
                for(int ed=st+1;ed<n;ed++){
                    getGraph(); 
                    ans=min(ans,dinic.Maxflow(st+n,ed));       //注意这里是st+n
                }
            }
            if(ans>n)ans=n;     //如果是完全图,最大流就是INF,只能全部删除,才能使得原图不连通
            printf("%d
    ",ans); 
        }   
    }
  • 相关阅读:
    贪心算法
    分治法
    递归法
    查找二 树与图的搜索
    (转载)查找三 哈希表的查找
    (转载)查找一 线性表的查找
    4.写出完整版的strcpy函数
    3.strcpy使用注意(3)
    2.strcpy使用注意(2)
    1.strcpy使用注意
  • 原文地址:https://www.cnblogs.com/00isok/p/10720631.html
Copyright © 2011-2022 走看看