首页 > 代码库 > hdu1598--结题报告

hdu1598--结题报告

题解:对于输入的边,我们首先按照速度从大到小排序,然后对于每一次询问,st   end 两个城市,我们暴力枚举,

for(int i = 0; i < M; i ++)  然后我们从第 i 条边开始(也就是说枚举删除0~i条边),到后面的第 M 条边,我们用krustra,向并查集中插入每一条边,看是不是能让st 和 end 联通,那么现在的 加入的这条边的速度 - 第i条边的速度就是 当前枚举情况的最小差啦,,我们与ans 比较一下取小值就可以break,进入下一条边的枚举啦。因为速度都是按小到大排序的,次条边能让st 和 end联通,再加边,只会让速度差更大

上马:

//187MS	300K
#include <iostream>
#include <algorithm>

using namespace std;

#define MAX 205
#define INF 1<<30

int N,M,Q;

struct Edge
{
    int st,end,speed;
    bool operator<(const Edge& E)const
    {
        return speed<E.speed;
    }
} edge[MAX*5];

int father[MAX];

int find(int x)
{
    if(x != father[x])
    {
        father[x] = find(father[x]);
    }
    return father[x];
}

int krustra(int st,int end)
{
    int ans = INF;
    //枚举
    for(int i = 0; i < M; i ++)
    {
        int j;
        for(j = 1; j <= N; j ++) father[j] = j;
        for(j = i; j < M; j ++)
        {
            father[find(edge[j].st)] = find(edge[j].end);
            //经过第i到第j条边的加入,我们可以使得st 和end 点联通
            //并且我们早已经按速度排序,那么差值就是下面的
            if(find(st) == find(end))
            {
                int pre = edge[j].speed - edge[i].speed;
                if(ans > pre) ans = pre;
                break;
            }
        }
        //这里表示,从第i第M条边,都不能让st 和end 联通,那么可以break
        if(j == M)
        {
            break;
        }
    }
    return ans;
}

int main()
{
    while(cin >> N >> M)
    {
        for(int i = 0; i < M ; i ++)
        {
            cin >> edge[i].st >> edge[i].end >> edge[i].speed;
        }
        sort(edge,edge+M);

        int ans;
        int st,end;
        cin >> Q;
        while (Q--)
        {
            cin >> st >> end;

            ans = krustra(st,end);

            if(ans == INF) cout << "-1" <<endl;
            else cout << ans <<endl;
        }
    }
    return 0;
}
个人愚昧观点,欢迎指正与讨论