bnuoj 20950 沉重的货物 (最小生成树)

沉重的货物

              Time Limit: 1000ms                                        Memory Limit: 65536KB
 64-bit integer IO format:  %lld      Java class name:  Main

 

CUITCPC是一个专门生产大型货运火车的工厂。他们的新型货运火车XX V1.0,是如此之大,以至于可以运输的货物的重量并不取决于那个火车本身,而只是受限于你所通过的铁路的承重。

给你出发和目标城市,你的任务就是求出火车从初始城市到目标城市的最大载重。

Input

 

输入可能包括一组或者多组测试数据。每一个测试数据的前两行是两个整数:城市的数量n(2<=n<=1000)和铁路的条数r(1<=r<= 19900)。

紧接着是r行,每一行描述一条连接两个城市的铁路以及这段铁路所能承受的最大重量。城市名不会超过30个字符,也不会有空白字符出现在城市名中。承重是一个0-10000的整数。铁路都是双向的。

最后一行是两个城市的名字:初始城市和目标城市。

输入的结束条件是n和r都为0

Output

 

对于每一组测试数据

输出包括3行:

l  一行输出"Scenario #x",其中x是测试数据的组数

l  一行输出"y tons",其中y表示最大载重量

l  一个空行

Sample Input

4 3
ACM ICPC 100
ICPC World 80
World CPC 120
ACM CPC
5 5
ACM ICPC 100
ICPC World 80
World CPC 120
ACM Chengdu 220
Chengdu CPC 170
CPC ACM
0 0

Sample Output

Scenario #1
80 tons

Scenario #2
170 tons

这是昨天晚上比赛的一道题,个人感觉这题还不错,只可惜当时没有做出来。读完题看出来了是一道最大流的题目,但我没有仔细的学过网络流,我按照书上的模板打完之后又发现不能直接套模板。比赛完听队友说也可以用最小生成树或者搜索来做,看来我想的太少了。

今天用最小生成树的思想写了一下这个题,每次往集合中添加一个距离起点最远的点,直到把终点添加进去,然后从这些边中选择一个最小值就是所求的答案。也许你会问:把终点添加进去就结束,那其他没有添加的点怎么办?会不会影响最终结果?  答案是不会。因为我们要求的是最大值,每次添加的都是较长的边,即使通过其他路径可以到达终点,但是通过其他路径得到的最大值肯定不会超过我们求出的结果。
#include<iostream>
#include<cstring>
#include<string>
#include<map>
using namespace std;
const int INF = 0x3fffffff;
const int N = 1e4;
int n, m, Min;
int cap[N][N], low[N], vis[N];
void Init(int n)
{
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= n; j++)
            cap[i][j] = -INF;
}
void Prim(int s, int e)
{
    int i, j;
    memset(vis, 0, sizeof(vis));
    memset(low, -1, sizeof(low));
    for(i = 1; i <= n; i++)
        if(cap[s][i] != -INF)
            low[i] = cap[s][i];
    vis[s] = 1;
    for(i = 1; i < n; i++)
    {
        int mmax = -1, pos;
        for(j = 1; j <= n; j++)
            if(!vis[j] && low[j] > mmax)
                mmax = low[pos = j];
        if(mmax == -1) break; //此句可加可不加,执行此句时肯定加入了已经n-1条边
        Min = Min < mmax ? Min : mmax;
        if(pos == e) break;
        vis[pos] = 1;
        for(j = 1; j <= n; j++)
            if(!vis[j] && cap[pos][j] > low[j])
                low[j] = cap[pos][j];
    }
}
int main()
{
    int i, j, t, w, cas = 1;
    map<string, int> mp;
    string str1, str2;
    while(cin >> n >> m)
    {
        if(!n && !m) break;
        Min = INF;
        mp.clear();
        Init(n);
        t = 1;
        for(i = 0;i < m; i++)
        {
            cin >> str1 >> str2 >> w;
            if(mp.find(str1) == mp.end())
                mp[str1] = t++;
            if(mp.find(str2) == mp.end())
                mp[str2] = t++;
            int x = mp[str1], y = mp[str2];
            cap[x][y] = cap[y][x] = w;
        }
        cin >> str1 >> str2;
        Prim(mp[str1], mp[str2]);
        cout << "Scenario #" << cas++ << endl;
        cout << Min << " tons" << endl;
        cout << endl;
    }
    return 0;
}


你可能感兴趣的:(最小生成树,STL)