• POJ-1459 Power Network---最大流


    题目链接:

    https://cn.vjudge.net/problem/POJ-1459

    题目大意:

    简单的说下题意(按输入输出来讲,前面的描述一堆的rubbish,还用来误导人),给你n个点,其中有np个是能提供电力的点,nc个是能消费电力的点,剩下的点(n-np-nc)是中转战即不提供电力也不消费电力,点与点之间是有线路存在的,有m条线路,每条线路有最多运载限定。
    前4个数据就是有n个点,np个供电点,nc个消费点,m条线路,接来题目先给出的是m条线路的数据,(起点,终点)最多运载量,然后是np个供电点的数据(供电点)最多供电量,接着就是nc个消费点的数据(消费点)最多消费电量。
    题目要我们求出给定的图最大能消费的总电量(就是求最大流)

    解题思路:

    传送门:网络流

    供电点有提供功能,那么供电点就可以当成源点,同样消费点有消费功能,可以当成汇点。
    由于这题有多个供电点和消费点,我们可以增加两个点,一个超级源点和一个超级汇点。
    把所有的供电点都当成是由超级源点提供电量的,所有的消费点都将消费电量转移到超级汇点上,这样就相当于转换成一个基本的网络流求最大流的题。
    超级源点与供电点有一条边,边的值为供电点最大能提供的电量,消费点与超级汇点有一条边,边的值为消费点最大能消费的电量。

    增加源点汇点这一技巧很常用。

     1 #include<iostream>
     2 #include<vector>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<queue>
     6 using namespace std;
     7 const int INF = 0x3f3f3f3f;
     8 const int maxn = 100 + 10;
     9 struct edge
    10 {
    11     int u, v, c, f;
    12     edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
    13 };
    14 vector<edge>e;
    15 vector<int>G[maxn];
    16 int a[maxn];//找增广路每个点的水流量
    17 int p[maxn];//每次找增广路反向记录路径
    18 void init(int n)
    19 {
    20     for(int i = 0; i <= n; i++)G[i].clear();
    21     e.clear();
    22 }
    23 void addedge(int u, int v, int c)
    24 {
    25     e.push_back(edge(u, v, c, 0));
    26     e.push_back(edge(v, u, 0, 0));
    27     int m = e.size();
    28     G[u].push_back(m - 2);
    29     G[v].push_back(m - 1);
    30 }
    31 int Maxflow(int s, int t)
    32 {
    33     int flow = 0;
    34     for(;;)//每次寻找增广路
    35     {
    36         memset(a, 0, sizeof(a));//初始化每个节点的流量均为0,源点流量为INF
    37         a[s] = INF;
    38         queue<int>q;
    39         q.push(s);
    40         while(!q.empty())
    41         {
    42             int u = q.front();
    43             q.pop();
    44             for(int i = 0; i < G[u].size(); i++)
    45             {
    46                 edge &now = e[G[u][i]];
    47                 int v = now.v;
    48                 if(!a[v] && now.c > now.f)//v点还未流经,且这条路还没流满
    49                 {
    50                     p[v] = G[u][i];//反向记录
    51                     a[v] = min(a[u], now.c - now.f);
    52                     q.push(v);
    53                 }
    54             }
    55             if(a[t])break;//已经到汇点
    56         }
    57         if(!a[t])break;//已经找不到增广路
    58         for(int u = t; u != s; u = e[p[u]].u)
    59         {
    60             e[p[u]].f += a[t];
    61             e[p[u] ^ 1].f -= a[t];
    62         }
    63         flow += a[t];
    64     }
    65     return flow;
    66 }
    67 int main()
    68 {
    69     int n, np, nc, m;//分别表示点数,电站数,居民数,边数
    70     while(cin >> n >> np >> nc >> m)
    71     {
    72         int s = n, t = n + 1;
    73         init(t);
    74         int u, v, c;
    75         for(int i = 0; i < m; i++)//建边
    76         {
    77             while(getchar() != '(');//读取左括号
    78             scanf("%d,%d)%d", &u, &v, &c);
    79             addedge(u, v, c);
    80         }
    81         for(int i = 0; i < np; i++)//对于每个电站,从源点到电站点连一条边,权值为电站发电值
    82         {
    83             while(getchar() != '(');
    84             scanf("%d)%d", &v, &c);
    85             addedge(s, v, c);
    86         }
    87         for(int i = 0; i < nc; i++)//对于每个居民,从居民点到汇点连一条边,权值是居民用电值
    88         {
    89             while(getchar() != '(');
    90             scanf("%d)%d", &u, &c);
    91             addedge(u, t, c);
    92         }
    93         cout<<Maxflow(s, t)<<endl;
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    docker备忘录
    GUAVA-RateLimit
    JDK各版本发展史
    C++ 基础备忘录
    浅谈MES
    MES在流程和离散制造企业的15个差别!
    mysql连接oracle补偿方案—odbc驱动
    WinForm控件Chart的图表类型
    C#的异常处理机制(try...catch...finally)
    oracle 横向列变为纵向列
  • 原文地址:https://www.cnblogs.com/fzl194/p/8858425.html
Copyright © 2020-2023  润新知