zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    mysql 日志
    mysql 事务中的锁
    mysql 事务的日志
    mysql 核心事务特性
    mysql 断电导致表打不开解决方案
    mysql 数据库逻辑升级
    mysql innodb存储引擎的表空间
    IDEA常用代码模板
    springcloud-GateWay常用的Predicate
    springcloud-GateWay配置动态路由
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2796880.html
Copyright © 2011-2022 走看看