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;
    }
  • 相关阅读:
    Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理
    Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析
    Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战
    超硬核Java学习路线图+学习资源+实战项目汇总,看完以后不用再问我怎么学Java了!
    还没使用过消息队列?这一份书单值得你好好看看!
    学习Spring,看这几本书就够了
    这份书单,想要晋级高级Java工程师的朋友值得一看!
    搞定JVM基本原理和面试题,看看这几本书妥妥够了!
    《自拍教程16》cmd的常用技巧
    《自拍教程15》命令行软件的通用技巧
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2796880.html
Copyright © 2011-2022 走看看