uva 4259 - Dangerous Tunnels 【二分 + 最大流】

题目链接:uva 4259 - Dangerous Tunnels

Somewhere in the world, there are two tribes separated by mountains. The two tribes are named Kulolo and Gulolo, respectively, where Kulolo is at a higher altitude and Gulolo is at a lower altitude. Due to the limitation of geography, Gulolo has fewer resources than Kulolo. In order to transport resources from Kulolo to Gulolo efficiently, several tunnels were built inside the mountains between these two tribes. There are also some rest stations built for people to take a break during the transportation in the tunnels. More specifically, each terminal of a tunnel is either Kulolo, Gulolo, or a rest station.

The structure of those tunnels is not stable. A dangerous degree has been estimated for each tunnel, due to its stability, in advance. A tunnel with a higher dangerous degree is considered to be more dangerous; that is, it is more probably to collapse. Kinglolo, the chief of Kulolo, would like to select some paths through the tunnels to Gulolo with little risk. In Kinglolo’s opinion, the dangerous degree of a path is equal to the maximum dangerous degree of the tunnels in the path; and the dangerous degree of a set of paths is equal to the maximum dangerous degree of the paths in it. For example, consider Figure 1. The dangerous degrees of P1, P2 , and P3 are, respectively, 3, 5, and 6. And, the dangerous degree of {P2, P3} is 6.

Since all tunnels are narrow, a limited quantity of resources can be transported along a path in one day. Therefore, every day, depending on the amount of resources needed to be transported, a different number, say k , of paths is required. Moreover, to avoid congestion, these k selected paths cannot pass any rest station in common. For example, in Figure 1, P2 and P3

\epsfbox{p4259.eps}
Figure 1: An example.
can be selected at the same time; however, P1 and P2 cannot be selected at the same time, since they both pass r2 . Kulolo has a higher altitude than all rest stations while Gulolo has a lower altitude than all rest stations. Kinglolo is a thoughtful chief. It is ensured that the altitudes of the rest stations on each selected path are non-increasing, so that the path is more suitable for transportation. For example, in Figure 1, the path (Kulolo, r3 , r1 , Gulolo) will never be selected, since r1 is higher than r3 .
People in Kulolo believe that Kinglolo is the most brilliant man in the world, since he always selects a set of k paths that is as little dangerous as possible (i.e., the maximum dangerous degree of the selected paths is minimized). Now, given the data of the constructed tunnels, you are asked to find k paths that Kinglolo may select. In summary, the k selected paths, if exist, should satisfy the following:

all paths are from Kulolo to Gulolo,
no two paths pass the same rest station,
the altitudes of the rest stations on each path are non-increasing, and
the maximum dangerous degree of the paths is minimized.

For simplicity, only the maximum dangerous degree of the selected paths should be reported.

Technical Specification

The number of rest stations, n : 0 < n 200 .
The number of tunnels, t : t > 0 .
The dangerous degree of a tunnel, d : 1 d 100000 .
The number of paths which should be selected, k : 1 k 10 .
Input

The input consists of multiple test cases. The first line of each case contains a positive integer n (0 < n 200) which indicates that there are n rest stations r1, r2,…, rn . For ease of description, Kulolo and Gulolo are denoted by r0 and rn+1 , respectively. We assume that ri is higher than rj for any 0 i < j n + 1 . The second line of each case contains a positive integer t (t > 0) that specifies the number of tunnels. Each of the following t lines contains three integers p , q , d (0 p n + 1, 0 q n + 1, p q, 1 d 100000) separated by white space, which indicate there is a tunnel with dangerous degree d connecting rp and rq . Then, a line containing a positive integer k (1 k 10) is provided, which is the number of paths that should be selected. You can assume that there is at most one tunnel between any two rest stations. The last test case is followed by a line containing a zero.

Output

For each test case, print a line containing the test case number (beginning with 1) followed by the maximum dangerous degree of the k paths that Kinglolo may select. If the solution does not exist, print “no solution”. Use the format of the sample output.

Sample Input

2
4
0 1 3
1 3 12
2 0 10
2 3 5
1
1
2
0 1 5
1 2 6
2
3
2
0 1 5
3 4 7
1
3
6
0 1 8
0 2 12
0 3 15
3 1 9
3 4 8
2 4 12
2
0
Sample Output

Case 1: 10
Case 2: no solution
Case 3: no solution
Case 4: 12

题意:n+2个点( 0 -n+1),m条路,每条路有一个危险系数且只能从i -> j (i < j)。现在要从0 到 n+1,要求必须选择k条路径且这k条路径不能经过一个点超过1次,记 d 为 k条路径中所有边的最大危险系数,问你最小的d。

思路:我们二分结果,根据结果构造网络流模型。因为每个点只能走一次,那么拆点就好了,最后看看最大流是否>=k即可。

AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 400 + 20;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
struct Edge {
    int from, to, cap, flow, next;
};
Edge edge[210 * 210 * 3];
int head[MAXN], cur[MAXN], edgenum;
void init() { CLR(head, -1); edgenum = 0; }
void addEdge(int u, int v, int w) {
    Edge E1 = {u, v, w, 0, head[u]};
    edge[edgenum] = E1;
    head[u] = edgenum++;
    Edge E2 = {v, u, 0, 0, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum++;
}
bool vis[MAXN]; int dist[MAXN];
bool BFS(int s, int t) {
    queue<int> Q; CLR(dist, -1); CLR(vis, false);
    dist[s] = 0; vis[s] = true; Q.push(s);
    while(!Q.empty()) {
        int u = Q.front(); Q.pop();
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            if(!vis[v] && edge[i].cap > edge[i].flow) {
                dist[v] = dist[u] + 1;
                if(v == t) return true;
                vis[v] = true;
                Q.push(v);
            }
        }
    }
    return false;
}
int DFS(int x, int a, int t) {
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int &i = cur[x]; i != -1; i = edge[i].next) {
        Edge &E = edge[i];
        if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(E.cap - E.flow, a), t)) > 0) {
            E.flow += f;
            edge[i^1].flow -= f;
            flow += f; a -= f;
            if(a == 0) break;
        }
    }
    return flow;
}
int Maxflow(int s, int t) {
    int flow = 0;
    while(BFS(s, t)) {
        memcpy(cur, head, sizeof(head));
        flow += DFS(s, INF, t);
    }
    return flow;
}
int n, m, k;
int u[210 * 210], v[210 * 210], w[210 * 210];
bool judge(int o) {
    init();
    for(int i = 1; i <= m; i++) {
        if(w[i] <= o) {
            addEdge(u[i] == 0 ? 0 : u[i] + n + 1, v[i], 1);
        }
    }
    for(int i = 1; i <= n; i++) {
        addEdge(i, i + n + 1, 1);
    }
    return Maxflow(0, n + 1) >= k;
}
int main()
{
    int kcase = 1;
    while(scanf("%d", &n), n) {
        scanf("%d", &m); int r = 0;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &u[i], &v[i], &w[i]);
            if(u[i] > v[i]) swap(u[i], v[i]);
            r = max(r, w[i]);
        }
        scanf("%d", &k);
        judge(10);
        int l = 1, ans = 0;
        while(r >= l) {
            int mid = (l + r) >> 1;
            if(judge(mid)) {
                ans = mid;
                r = mid - 1;
            }
            else {
                l = mid + 1;
            }
        }
        if(ans == 0) {
            printf("Case %d: no solution\n", kcase++);
        }
        else {
            printf("Case %d: %d\n", kcase++, ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值