uva 10330 Power Transmission

最大流水题

题意:给n个点从1到n标号,每个点有一个限制值a[i],表示从这个点流出的流量的最大值,就算有超过a[i]的流量流进i点,最后也只有a[i]流量从i点流出。然后每条有向边也有容量cap[u][v]

然后给你一个源点0,它会和一些顶点相连,这些边的容量是无穷大的,然后给你一个汇点n+1,也会和一些顶点相连,这些边的容量也是无穷大的,

然后求源点到汇点的最大流

想了一下,有思路,无非是处理一下边的容量,起初想是对于有向边  u---->v  cap[u][v]=min( cap[u][v] , a[u]);  处理完就直接最大流模板上去,过了sample,提交WA,后来才想到是

cap[u][v]=min( cap[u][v] , a[u] , a[v]);  提交WA………………才想起来,那些无穷大的边的容量没有做处理,和源点关联的边的容量由无穷大改为与之相连的那个点的限制值a[v] ,与汇点关联的那些边的容量改为那个点的限制值a[u],然后最大流模板直接上去,AC了,水题遂过

 

然后查了一下网上的解题报告,说是要拆成两点,然后连一条边,容量就是限制值,拆点的代码这里没给出,下次再写了

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;

#define N 110

#define INF 0x3f3f3f3f

int cap[N][N];

int n,m,numb,numd;  //源点和汇点

int a[N]; //a是每个顶点的限制量



void input()

{

    memset(cap,0,sizeof(cap));

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

        scanf("%d",&a[i]);

    scanf("%d",&m);

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

    {

        int u,v,w;

        scanf("%d%d%d",&u,&v,&w);

        cap[u][v]+=w;

        if(cap[u][v]>a[u])

            cap[u][v]=a[u];

        if(cap[u][v]>a[v])

            cap[u][v]=a[v];

    }

    scanf("%d%d",&numb,&numd);

    for(int i=1; i<=numb; i++)

    {

        int v;

        scanf("%d",&v);

        cap[0][v]=a[v];

    }

    for(int i=1; i<=numd; i++)

    {

        int u;

        scanf("%d",&u);

        cap[u][n+1]=a[u];

    }



    return ;

}

void print_graph()

{

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

    {

        for(int j=0; j<=n+1; j++)

            printf("%d ",cap[i][j]);

        printf("\n");

    }

    return ;

}

void EK()

{

    int F=0;  //记录最终最大流

    int min[N];  //记录最小残余流量

    int p[N];  //记录路径

    int flow[N][N];  //流量

    memset(flow,0,sizeof(flow));

    while(1)

    {

        memset(min,0,sizeof(min)); min[0]=INF;  //递推数组,每次增广路找最小值

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

        queue <int> q;

        q.push(0);

        while(!q.empty())  //BFS

        {

            int u=q.front(); q.pop();

            for(int v=0; v<=n+1; v++)

                if( !min[v] && cap[u][v]>flow[u][v])

                {

                    p[v]=u; q.push(v);

                    min[v]=min[u]<(cap[u][v]-flow[u][v]) ? min[u] : (cap[u][v]-flow[u][v]);

                }

        }



        if(!min[n+1])  break;

        

        for(int u=n+1; u!=0; u=p[u])  //增广

        {

            flow[p[u]][u]+=min[n+1];

            flow[u][p[u]]-=min[n+1];

        }

        F+=min[n+1];

    }

    printf("%d\n",F);

}

int main()

{

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

    {

        input();

        //print_graph();

        EK();  //EK算法求最大流

    }

    return 0;

}

你可能感兴趣的:(SSI)