poj 3204(最大流处理)

Ikki's Story I -  Road Reconstruction

Time Limit: 2000MS Memory Limit: 131072K
Total Submissions: 4830 Accepted: 1317

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 N, M (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 a, b,c, which means that there is a road from city a to city b with a transportation capacity ofc (0 ≤ a, b < n, c ≤ 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 numberedn − 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

Source

POJ Monthly--2007.03.04, Ikki

暂且说这是求关键边的数量吧。。。。思路是这样的。。利用求最大流的过程中会对建立的图中的流量进行增减,所以最大流处理后会出现流量为0的正向边(程序中会给出问什么要说正向边),但也会出现0->0->0这样类似的边。。。所以排除这种不是在这条路上唯一为0的边之后,其余为0的边的数量即为所求,这里可以对最大流处理后的图进行搜索两次,看s源点能否到这条流量为0的边,和t汇点能否到达这条流量为0的边就可以解决问题了。。。。


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxM 100000
#define maxN 550
#define inf INT_MAX
#define CC(m,v) memset(m,v,sizeof(m))

struct node {
    int u, v, f, next;
} edge1[maxM], edge2[maxM];
int head1[maxN], head2[maxN], p, p2;
int que[maxN], pi, lev[maxN], cur[maxN];
int vis1[maxN], vis2[maxN];

inline void init1() {
    p = p2 = 0, CC(head1, -1), CC(head2, -1);
}

void addedge(int u, int v, int f) {
    edge1[p].u = u, edge1[p].v = v, edge1[p].f = f, edge1[p].next = head1[u], head1[u] = p;
    edge2[p].u = u, edge2[p].v = v, edge2[p].f = 0, edge2[p].next = head2[u], head2[u] = p++;
    edge1[p].u = v, edge1[p].v = u, edge1[p].f = 0, edge1[p].next = head1[v], head1[v] = p;
    edge2[p].u = v, edge2[p].v = u, edge2[p].f = f, edge2[p].next = head2[v], head2[v] = p++;
}

bool bfs(int s, int t) {
    int fir, en, u, v, i;
    memset(lev, 0, sizeof (lev));
    lev[s] = 1, que[0] = s, fir = 0, en = 1;
    while (fir != en) {
        u = que[fir++];
        for (i = head1[u]; i != -1; i = edge1[i].next)
            if (edge1[i].f > 0 && lev[v = edge1[i].v] == 0) {
                lev[v] = lev[u] + 1, que[en++] = v;
                if (v == t) {
                    fir = en;
                    break;
                }
            }
    }
    return lev[t];
}

int dinic(int s, int t) {
    int u, j, k, iq, f;
    int flow = 0;
    while (bfs(s, t)) {
        memcpy(cur, head1, sizeof (head1));
        u = s, iq = 0;
        while (1) {
            if (u == t) {
                for (k = 0, f = inf; k < iq; k++)
                    if (edge1[que[k]].f < f)
                        f = edge1[que[k]].f, j = k;
                for (k = 0; k < iq; k++) {
                    edge1[que[k]].f -= f, edge1[que[k]^1].f += f;
                    edge2[que[k]].f += f, edge2[que[k]^1].f -= f;
                }
                flow += f, u = edge1[que[iq = j]].u;
            }
            for (j = cur[u]; cur[u] != -1; j = cur[u] = edge1[cur[u]].next)
                if (edge1[j].f > 0 && lev[u] + 1 == lev[edge1[j].v]) break;
            if (cur[u] != -1) {
                que[iq++] = cur[u];
                u = edge1[cur[u]].v;
            } else {
                if (iq == 0) break;
                lev[u] = -1;
                u = edge1[que[--iq]].u;
            }
        }
    }
    return flow;
}

void dfs1(int u) {
    vis1[u] = 1;
    for (int i = head1[u]; i != -1; i = edge1[i].next)
        if (edge1[i].f > 0 && vis1[edge1[i].v] == 0)
            dfs1(edge1[i].v);
}

void dfs2(int u) {
    vis2[u] = 1;
    for (int i = head2[u]; i != -1; i = edge2[i].next)
        if (edge2[i].f > 0 && vis2[edge2[i].v] == 0)
            dfs2(edge2[i].v);
}

int main() {
    int n, m, i, u, v, f, ans;

    scanf("%d%d", &n, &m);
    init1();
    for (i = 1; i <= m; i++) {
        scanf("%d%d%d", &u, &v, &f);
        addedge(u, v, f);
    }
    if (dinic(0, n - 1) == 0) {
        printf("0\n");
    } else {
        CC(vis1, 0), CC(vis2, 0);
        dfs1(0), dfs2(n - 1);
        for (i = 0, ans = 0; i < p; i += 2) // +=2是重点,因为回退边肯定不为0
            if (edge1[i].f <= 0 && vis1[edge1[i].u] && vis2[edge1[i].v])
                ans++;
        printf("%d\n", ans);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值