ACM-ICPC Live Archive 3031 Cable TV Network

求解无向图的点连通度,转化为网络流

详细的解释明天再写了

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;

#define N 60

#define min(a,b) a<b?a:b

#define max(a,b) a>b?a:b

#define INF 0x3f3f3f3f



int first[10*N];

struct edge

{

    int u,v,cap,flow,next;

}e[N*N*N];

int nume;

int n,m;



void EK(int s ,int t ,int &MIN)

{

    int FLOW=0;

    while(1)

    {

        queue<int>q;

        int a[10*N];

        int p[10*N];

        memset(a,0,sizeof(a));

        memset(p,-1,sizeof(p));

        a[s]=INF;

        while(!q.empty()) q.pop();

        q.push(s);

        while(!q.empty())

        {

            int u,v,cap,flow;

            u=q.front(); 

            q.pop();

            for(int k=first[u]; k!=-1; k=e[k].next)

            {

                v=e[k].v; cap=e[k].cap; flow=e[k].flow;

                if(!a[v] && cap>flow) //未访问且可增流

                {

                    a[v]=min(a[u] , cap-flow);

                    p[v]=k;

                    q.push(v);

                }

            }

        }

        if(!a[t]) break; //不可增广

        for(int k=p[t]; k!=-1; k=p[e[k].u])

        {

            e[k].flow += a[t];

            e[k^1].flow -= a[t];

        }

        FLOW += a[t];

    }

    MIN=min(MIN,FLOW);

}



void init()

{

    for(int i=0; i<nume; i++) e[i].flow=0;

}



void solve(int s)

{

    int MIN=INF;

    for(int t=1; t<n; t++)//枚举汇点

    {

        EK(s,t,MIN);

        init();

    }

    if(MIN>=INF) printf("%d\n",n);

    else         printf("%d\n",MIN);

}



void add(int u ,int v , int cap)

{

    e[nume].u=u; e[nume].v=v; e[nume].cap=cap; e[nume].flow=0;

    e[nume].next=first[u]; first[u]=nume++;



    e[nume].u=v; e[nume].v=u; e[nume].cap=0; e[nume].flow=0;

    e[nume].next=first[v]; first[v]=nume++;

}



int main()

{

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        if(m==0)

        {

            if(n==1)printf("1\n");

            else    printf("0\n");

            continue;

        }

        memset(first,-1,sizeof(first));

        nume=0;

        for(int i=0; i<n; i++) 

            add(i,i+n,1);

        for(int i=0; i<m; i++)

        {

            int u,v; char s[20];

            scanf("%s",s);

            sscanf(s+1,"%d",&u);

            for(int j=0; s[j]!='\0'; j++) if(s[j]==',')

            { sscanf(s+j+1,"%d",&v); break;}

            //拆点,拆为u,u+n,

            add(u+n,v,INF); 

            add(v+n,u,INF);

        }

        solve(n);

    }

    return 0;

}

 

你可能感兴趣的:(NetWork)