POJ 2263 Heavy Cargo 【最小瓶颈路相关】

传送门
// 题意: 给定一个无向图(n, m),在给定一个起点和终点, 问地点和终点中可能路径中的最大的那条边的权值是多少.

// 思路: 这个问题还是比较经典, 很多题都要这个问题, 那么我们看这个数据范围, 200,可以跑floyd, 得出任意两点之间的距离的最大的边, 就是对floyd进行一些小的膜改. 首先初始化矩阵是我们应该同一点初始化为inf, 不同点初始化为0, 然后0代表不能到达, 所以floyd中关键语句为:
if (g[i][k] && g[k][j])
g[i][j] = max(g[i][j], min(g[i][k], g[k][j]));

然后就可以通过此题了.

AC Code

const int maxn = 2e2+5;
int cas=1;
int g[maxn][maxn];
map<string, int>mp;
int n, m;
void floyd() {
    for (int k = 1 ;  k <= n ; k ++) {
        for (int i = 1 ; i <= n ; i ++) {
            for (int j = 1 ; j <= n ; j ++) {
                if (g[i][k] && g[k][j])
                    g[i][j] = max(g[i][j], min(g[i][k], g[k][j]));
            }
        }
    }
}
void solve()
{
    while(cin >> n >> m ) {
        if (n + m == 0) break;
        for (int i = 1 ; i <= n ; i ++) {
            for (int j = 1 ; j <= n ; j ++) {
                if (i == j) g[i][j] = inf;
                else g[i][j] = 0;
            }
        }
        Fill(g, 0);
        int cnt = 0; mp.clear();
        for (int i = 1 ; i <= m ; i ++) {
            string s1, s2; int w;
            cin >> s1 >> s2 >> w;
            if (!mp[s1]) mp[s1] = ++cnt;
            if (!mp[s2]) mp[s2] = ++cnt;
            g[mp[s1]][mp[s2]] = g[mp[s2]][mp[s1]] = w;
        }
        floyd();
        string s1, s2;
        cin >> s1 >> s2;
        int s = mp[s1]; int t = mp[s2];
        printf("Scenario #%d\n", cas++);
        if (s != t) cout << g[s][t] << " tons" << endl << endl;
        else cout << 0 << " tons" << endl << endl;
    }
}

那我们想一想如果数据量比较大了? 当然dij也能过. 但是我要说一种比dij简单一点的方法, 也就是并查集.
我们首先将边的信息按从大到小排一个序, 然后贪心的从大的开始选, 并把他们并在一起, 如果某次并的过程中发现我们要对源点 和 汇点 并在一起了, 我们此时的边权也就是我们的ans. 这个方法就很好啦~.

AC Code(并查集)

const int maxn = 2e2+5;
int cas=1;
struct node {
    int u, v, w;
    bool operator < (const node & a) const {
        return w > a.w;
    }
}e[maxn*maxn];
int fa[maxn];
int Find(int x) {
    return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
void solve()
{
    int n, m;
    while(cin >> n >> m) {
        if (n + m == 0) break;
        map<string, int>mp; int cnt = 0;
        for (int i = 1 ; i <= n ; i ++) fa[i] = i;
        for (int i = 1 ; i <= m ; i ++) {
            string s1, s2; int w;
            cin >> s1 >> s2 >> w;
            if (!mp[s1]) mp[s1] = ++cnt;
            if (!mp[s2]) mp[s2] = ++cnt;
            e[i].u = mp[s1]; e[i].v = mp[s2];
            e[i].w = w;
        }
        sort(e+1, e+1+m);
        string s1, s2;
        cin >> s1 >> s2;
        int s = mp[s1]; int t = mp[s2];
        int ans = 0;
        for (int i = 1 ; i <= m ; i ++) {
            int u = Find(e[i].u);
            int v = Find(e[i].v);
            if (u != v) fa[u] = v;
            if (Find(s) == Find(t)) {
                ans = e[i].w;
                break;
            }
        }
        printf("Scenario #%d\n", cas++);
        cout << ans << " tons" << endl << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值