uva 10330 Power Transmission (最大流 + 拆点)

uva 10330 Power Transmission

如果对最大流不熟悉的话可以先去看看这个

题目大意:先来讲解一下INPUT。首先读入一个正整数N, 接下来N个数据是N个调节器的容量;然后读入一个正整数M, 接下来M组数据代表的是M条调节器与调解器之间的线路(调节器u, 调节器v, 容量);最后的一组数据先是两个正整数a和b, 接下来的a个数据代表的是初始的调节器,最后的b个数据代表的是终结的调节器。

综上,求最大流。

解题思路:源点或汇点不唯一的时候,记得要增加超级源点或超级汇点来使得源点,汇点唯一。一开始N个调节器结点是有容量的,所以要把N个调节器给拆开,每个调节器都要拆成 调节器=调节器(左)+容量+调节器(右),拆点结束之后就得到一张图,然后用EK算法,算出最大流。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
typedef long long ll;
const int OF = 100;
const int INF = 0x3f3f3f3f;
const int N = 500;
int n, m, G[N][N], f[N][N];
void Input() { //把一开始的N个regulator(调节器)拆成两个点一条路
    memset(G, 0, sizeof(G));
    memset(f, 0, sizeof(f));
    int num;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &num);
        G[i + OF][i] = num;
    }
    scanf("%d", &m);
    int a, b, c;
    for (int i = 0; i < m; i++) {
        scanf("%d %d %d", &a, &b, &c);
        G[a][b + OF] = c;
    }
    scanf("%d %d", &a, &b);
    for (int i = 0; i < a; i++) { //增加超级源点
        scanf("%d", &c);
        G[0][c + OF] = INF;
    }
    for (int i = 0; i < b; i++) { //增加超级汇点
        scanf("%d", &c);
        G[c][n + OF + 1] = INF;
    }
}
int EK() {
    queue<int> Q;
    n = n + OF + 1;
    int pre[N], a[N], ans = 0;
    memset(f, 0, sizeof(f));
    while (1) {
        memset(pre, 0, sizeof(pre));
        memset(a, 0, sizeof(a));
        a[0] = INF;
        Q.push(0);
        while (!Q.empty()) { //BFS找增广路
            int u = Q.front(); Q.pop();
            for (int v = 0; v <= n; v++) {
                if (!a[v] && G[u][v] > f[u][v]) { //找到新结点
                    pre[v] = u; //记录新节点的父亲
                    Q.push(v);  //加入FIFO队列
                    a[v] = min(a[u], G[u][v] - f[u][v]); //s - t的最小残量
                }
            }
        }
        if (a[n] == 0) break; //当找不到新的增广路时,就已是最大流
        ans += a[n]; //更新从s流出的总流量
        for (int u = n; u != 0; u = pre[u]) { //从源点s往回走
            f[pre[u]][u] += a[n];   //更新正向边
            f[u][pre[u]] -= a[n];   //更新反向边
        }

    }
    return ans;
}
int main() {
    while (scanf("%d", &n) != EOF) {
        Input(); //读入数据,拆点
        printf("%d\n", EK());
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 15:41:15

uva 10330 Power Transmission (最大流 + 拆点)的相关文章

UVA 10330 Power Transmission(网络最大流)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1271  Power Transmission  The Problem DESA is taking a new project to transfer power. Power is generated by the newly established plant in Barisal.

UVA 10330 Power Transmission

题意:懒得打了.LUCKY CAT 里有 http://163.32.78.26/homework/q10330.htm 第一个网络流题目.每个节点都有一个容量值.需要拆点.拆成i - > i + N  边权为容量值 另外注意B个点 连接方式:s - 集合B D个点 链接方式 集合D + N -> t汇点 其他看处理就好 #include <map> #include <set> #include <list> #include <cmath>

light oj 1155 - Power Transmission【拆点网络流】

1155 - Power Transmission   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB DESA is taking a new project to transfer power. Power is generated by the newly established plant in Barisal. The main aim of this project is to tr

UVa 10298 - Power Strings

题目:求一个串的最大的循环次数. 分析:dp,KMP,字符串.这里利用KMP算法. KMP的next函数是跳跃到最近的串的递归结构位置(串元素取值0 ~ len-1): 由KMP过程可知: 如果存在循环节,则S[0 ~ next[len]-1] 与 S[len-next[len] ~ len-1]相匹配: 则S[next[len] ~ len-1]就是循环节(且最小),否则next[len]为0: 因此,最大循环次数为len/(len-next[len]),最小循环节为S[next[len] ~

hdu 4289 Control(网络流 最大流+拆点)(模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1545    Accepted Submission(s): 677 Problem Description You, the head of Department o

POJ3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 题意:有一个n*n的矩阵,格子中的元素是费用,KaKa从左上角开始出发要到达右下角,但是他只能向下走或者向右走,且走过的格子赋值为0,可以走K次,问K次后KaKa能获得的最大费用是多少? 思路:首先解释一下为什么要拆点?    因为要获得最大费用,所以假设当前步选择先下走,最终得到的结果可能不是最大值,但根据题意却把走过的格子赋为0了,这就影响了最终结果.所以进行拆点,把每个点拆成两个点,入度点和出度点,本点的入度点连接着本

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma

UVA 11149 - Power of Matrix(矩阵倍增)

UVA 11149 - Power of Matrix 题目链接 题意:给定一个n*n的矩阵A和k,求∑kiAi 思路:利用倍增去搞,∑kiAi=(1+Ak/2)∑k/2iAi,不断二分即可 代码: #include <cstdio> #include <cstring> const int N = 45; int n, k; struct mat { int v[N][N]; mat() {memset(v, 0, sizeof(v));} mat operator * (mat

POJ 3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking