UVA-1660 Cable TV Network (最小割)

题目大意:给一张n个点、m条边的无向图,求最小点割集的基数。

题目分析:求无向图最小点割集的基数可以变成求最小割。考虑单源s单汇t的无向图,如果要求一个最小点集,使得去掉这个点集后图不再连通(连通分量数目增多),只需将每个点拆成两个(入点和出点),并且之间连一条容量为1的弧,其他弧不变,在新网络上求最小割便得到这个最小点集的基数。但是本题无源无汇,可以指定一个点作为源点,枚举其它的点作为汇点,求得n-1个点集基数,取最小的便是答案。要注意每次枚举都要重新建图。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

const int INF=1<<30;
const int maxn=105;

struct Edge
{
    int fr,to,cap,fw;
    Edge(int fr,int to,int cap,int fw){
        this->fr=fr;
        this->to=to;
        this->cap=cap;
        this->fw=fw;
    }
};
struct Dinic
{
    vector<Edge>edges;
    vector<int>G[maxn];
    int d[maxn],cur[maxn];
    int vis[maxn],n,s,t;

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

    void addEdge(int u,int v,int cap)
    {
        edges.push_back(Edge(u,v,cap,0));
        edges.push_back(Edge(v,u,0,0));
        int m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }

    bool bfs()
    {
        memset(vis,0,sizeof(vis));
        vis[s]=1;
        d[s]=0;
        queue<int>q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0;i<G[u].size();++i){
                Edge& e=edges[G[u][i]];
                if(e.cap>e.fw&&!vis[e.to]){
                    vis[e.to]=1;
                    d[e.to]=d[u]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int u,int a)
    {
        if(u==t||a==0) return a;
        int flow=0,f;
        for(int &i=cur[u];i<G[u].size();++i){
            Edge& e=edges[G[u][i]];
            if(d[e.to]==d[u]+1&&(f=dfs(e.to,min(a,e.cap-e.fw)))>0){
                e.fw+=f;
                edges[G[u][i]^1].fw-=f;
                flow+=f;
                a-=f;
                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;
    }
};
Dinic solver;
string p;
int n,m,mark[55];
vector<Edge>E;

void addEdge(int u,int v,int cap)
{
    E.push_back(Edge(u,v,cap,0));
}

void solve()
{
    int len=p.size(),pos;
    for(pos=0;pos<len;++pos)
        if(p[pos]==',') break;
    int a=0,b=0;
    for(int i=1;i<pos;++i)
        a=a*10+p[i]-'0';
    for(int i=pos+1;i<len-1;++i)
        b=b*10+p[i]-'0';
    addEdge(a<<1|1,b<<1,INF);
    addEdge(b<<1|1,a<<1,INF);
}

void look()
{
    for(int i=0;i<solver.edges.size();++i){
        Edge& e=solver.edges[i];
        cout<<e.fr<<' '<<e.to<<' '<<e.cap<<' '<<e.fw<<endl;
    }
}

int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        E.clear();
        for(int i=0;i<n;++i) addEdge(i<<1,i<<1|1,1);
        while(m--)
        {
            cin>>p;
            solve();
        }
        //look();
        int ans=n,k=E.size();
        for(int i=1;i<n;++i){
            solver.init(n*2);
            for(int j=0;j<k;++j){
                solver.addEdge(E[j].fr,E[j].to,E[j].cap);
            }
            int flow=solver.maxFlow(1,i<<1);
            ans=min(ans,flow);
        }
        printf("%d\n",ans);
    }
    return 0;
}

  

posted @ 2016-01-09 22:36  20143605  阅读(456)  评论(0编辑  收藏  举报