题解【POJ1797】Heavy Transportation

题面

题意简述:

\(n\) 个点,\(m\) 条边,每条边有权值。求一条 \(1\) 号点到 \(n\) 号点的路径,要求使得路径中的边权最小值最大。

\(\texttt{Data Range: }1 \le n \le 1000,\ 0< w \le 10^6。\)

看到最小值最大,直接二分答案。

二分一个 \(mid\),只考虑所有边权 \(\ge mid\) 的边,看 \(dis_n\) 是不是 INF 即可。

时间复杂度 \(O(m\log n\log 10^6)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair <int, int> PII;

inline int gi()
{
	int f = 1, x = 0; char c = getchar();
	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f * x;
}

const int N = 100003, M = N << 1;

int T;
int n, m;
int tot, head[N], ver[M], nxt[M], edge[M];
int dis[N];
bool vis[N];

inline void add(int u, int v, int w)
{
    ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
}

void Dij(int x)
{
    priority_queue <PII> q;
    q.push(make_pair(0, 1));
    memset(vis, 0, sizeof vis);
    memset(dis, 0x3f, sizeof dis);
    while (!q.empty())
    {
        int u = q.top().second; q.pop();
        if (vis[u]) continue; vis[u] = true;
        for (int i = head[u]; i; i = nxt[i])
        {
            int v = ver[i], w = edge[i];
            if (w < x) continue;
            if (dis[v] > min(dis[u], w))
            {
                dis[v] = min(dis[u], w);
                q.push(make_pair(-dis[v], v));
            }
        }
    }
}

inline bool check(int x)
{
    Dij(x);
    if (dis[n] != 0x3f3f3f3f) return true;
    return false;
} 

int main()
{
    T = gi();
    int Case = 0;
    while (T--)
    {
        memset(head, 0, sizeof head);
        tot = 0;
        n = gi(), m = gi();
        int l = 1000001, r = 0;
        for (int i = 1; i <= m; i+=1)
        {
            int u = gi(), v = gi(), w = gi();
            add(u, v, w), add(v, u, w);
            l = min(l, w), r = max(r, w);
        }
        int ans = 0;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (check(mid)) ans = mid, l = mid + 1;
            else r = mid - 1;
        }
        printf("Scenario #%d:\n%d\n\n", ++Case, ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xsl19/p/12891249.html