【poj3204】枚舉割邊

Ikki's Story I - Road Reconstruction

Time Limit: 2000MS   Memory Limit: 131072K
Total Submissions: 8360   Accepted: 2423

Description

Ikki is the king of a small country – Phoenix, Phoenix is so small that there is only one city that is responsible for the production of daily goods, and uses the road network to transport the goods to the capital. Ikki finds that the biggest problem in the country is that transportation speed is too slow.

Since Ikki was an ACM/ICPC contestant before, he realized that this, indeed, is a maximum flow problem. He coded a maximum flow program and found the answer. Not satisfied with the current status of the transportation speed, he wants to increase the transportation ability of the nation. The method is relatively simple, Ikki will reconstruct some roads in this transportation network, to make those roads afford higher capacity in transportation. But unfortunately, the country of Phoenix is not so rich in GDP that there is only enough money to rebuild one road. Ikki wants to find such roads that if reconstructed, the total capacity of transportation will increase.

He thought this problem for a loooong time but cannot get it. So he gave this problem to frkstyc, who put it in this POJ Monthly contest for you to solve. Can you solve it for Ikki?

Input

The input contains exactly one test case.

The first line of the test case contains two integers NM (N ≤ 500, M ≤ 5,000) which represents the number of cities and roads in the country, Phoenix, respectively.

M lines follow, each line contains three integers abc, which means that there is a road from city a to city b with a transportation capacity of c (0 ≤ ab < nc ≤ 100). All the roads are directed.

Cities are numbered from 0 to n − 1, the city which can product goods is numbered 0, and the capital is numbered n − 1.

Output

You should output one line consisting of only one integer K, denoting that there are K roads, reconstructing each of which will increase the network transportation capacity.

Sample Input

2 1
0 1 1

Sample Output

1

題目大意:從源點0到匯點n-1,求增大哪些邊會增大整個網絡的容量,輸出邊的數量

首先枚舉割邊,即滿流邊,就是容量=流量,比如u->v是滿流邊,判斷0到u和v到n-1能否流通,如果能,則ans+1

#include<cstring>
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 4005;
const int maxm = maxn * maxn;
const int inf = 0x3f3f3f3f;
class Dinic {
public :
    struct Node {
        int u, v, f, next;
    }e[maxm];

    int head[maxn], p, lev[maxn], cur[maxn];
    int que[maxm];

    void init() {
        p = 0; 
        memset(head, -1, sizeof(head));
    }

    void add(int u, int v, int f) {
        e[p].u = u; e[p].v = v; e[p].f = f; e[p].next = head[u]; head[u] = p++;
        e[p].u = v; e[p].v = u; e[p].f = 0; e[p].next = head[v]; head[v] = p++;
    }

    bool bfs(int s, int t) {
        if(s==t)return 1;//這一句此前沒有,爲當前題目特有,具體問題具體分析
        int u, v, qin = 0, qout = 0;
        memset(lev, 0, sizeof(lev)); lev[s] = 1; que[qin++] = s;
        while(qout != qin) {
            u = que[qout++];
            for(int i = head[u]; i != -1; i = e[i].next) {
                if(e[i].f > 0 && !lev[v = e[i].v]) {
                    lev[v] = lev[u] + 1, que[qin++] = v;
                    if(v == t) return 1;
                }
            }
        }
        return 0;
    }

    int dfs(int s, int t) {
        int i, f, qin, u, k;
        int flow = 0;
        while(bfs(s, t)) {
            memcpy(cur, head, sizeof(head));
            u = s, qin = 0;
            while(1) {
                if(u == t) {
                    for(k = 0, f = inf; k < qin; k++)
                        if(e[que[k]].f < f) f = e[que[i=k]].f;
                    for(k = 0; k < qin; k++)
                        e[que[k]].f -= f, e[que[k]^1].f += f;
                    flow += f, u = e[que[qin = i]].u;
                }
                for(i = cur[u]; cur[u] != -1; i = cur[u] = e[cur[u]].next)
                    if(e[i].f > 0 && lev[u] + 1 == lev[e[i].v]) break;
                if(cur[u] != -1)
                    que[qin++] = cur[u], u = e[cur[u]].v;
                else {
                    if(qin == 0) break;
                    lev[u] = -1, u = e[que[--qin]].u;
                }
            }
        }
        return flow;
    }
};
Dinic g;
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        g.init();
        for(int i=0;i<m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            g.add(a,b,c);
        }
        while(g.bfs(0,n-1))
            g.dfs(0,n-1);
        int ans=0;
        for(int i=0;i<g.p;i++){
            if(i%2==0&&g.e[i].f==0&&g.e[i].u!=g.e[i].v){//只考慮正向邊
                if(g.bfs(0,g.e[i].u)&&g.bfs(g.e[i].v,n-1))
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章