poj1966Cable TV Network——无向图最小割(最大流)

题目:http://poj.org/problem?id=1966

把一个点拆成入点和出点,之间连一条边权为1的边,跑最大流即最小割;

原始的边权赋成inf防割;

枚举源点和汇点,直接相邻的两个点不必枚举;

注意:1、源点为枚举点i的出点,汇点为枚举点j的入点;

   2、读入方式,免空格;

   3、在dinic跑最大流的过程中,会改变边权,因此每次枚举都要复制一组边跑最大流,以免影响后面;

另:数据中的点从0开始,所以读入的时候++来使用。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
int n,m,head[105],cur[105],ct=1,inf=1e9,ans,d[105];
bool sid[55][55];
struct N{
    int to,next,w;
    N(int t=0,int n=0,int ww=0):to(t),next(n),w(ww) {}
}edge[6005],ed[6005];
void add(int x,int y,int z)
{
    ed[++ct]=N(y,head[x],z);head[x]=ct;
    ed[++ct]=N(x,head[y],0);head[y]=ct;
}
bool bfs(int s,int t)
{
    memset(d,0,sizeof d);
    while(q.size())q.pop();
    d[s]=1;q.push(s);
    while(q.size())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=edge[i].next)
        {
            int u=edge[i].to;
            if(!d[u]&&edge[i].w)
            {
                d[u]=d[x]+1;
                q.push(u);
            }
        }
    }
    return d[t];
}
int dfs(int x,int f,int t)
{
    if(x==t)return f;
    int res=0;
    for(int i=cur[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(d[u]==d[x]+1&&edge[i].w)
        {
            int tmp=dfs(u,min(edge[i].w,f-res),t);
            edge[i].w-=tmp;
            edge[i^1].w+=tmp;
            res+=tmp;
            if(edge[i].w)cur[x]=i;
            if(res==f)return f;
        }
    }
    if(!res)d[x]=0;
    return res;
}
int dinic(int s,int t)
{
    memcpy(edge,ed,sizeof ed);//!!!
    int res=0;
    while(bfs(s+n,t))
    {
        for(int i=0;i<=2*n;i++)cur[i]=head[i];
        res+=dfs(s+n,inf,t);
    }
    return res;
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        if(!n||n==1)
        {
            printf("%d\n",n);
            continue;
        }
        if(!m)
        {
            printf("0\n");
            continue;
        }
        ct=1;ans=inf;
        memset(head,0,sizeof head);
        memset(sid,0,sizeof sid);
        for(int i=1;i<=n;i++)add(i,i+n,1);
//        char dc=0;
        for(int i=1;i<=m;i++)
        {
//            dc=0;
//            while(dc!='(')scanf("%c",&dc);
            int x,y;
            scanf(" (%d,%d)",&x,&y);//或者采用注释方法读入,这里为 scanf("%d,%d",&x,&y);
            x++;y++;//
            sid[x][y]=1;sid[y][x]=1;
            add(x+n,y,inf);
            add(y+n,x,inf);
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(!sid[i][j])ans=min(ans,dinic(i,j));
        if(ans==inf)ans=n;
        printf("%d\n",ans);
//        dc=0;
//        while(dc!=')')scanf("%c",&dc);
    }
    return 0;
}

 

posted @ 2018-03-22 00:10  Zinn  阅读(921)  评论(0编辑  收藏  举报