标签:
Description
Input
Output
Sample Input
4 4 1 2 2 2 3 4 1 4 1 3 4 2 2 1 3 1 2
Sample Output
1 0
思路:根据cruskal的思想,每次把最小的边加入到已选的集合里面。
一旦已选集合里出现了start和end,记录最大边与最小边的差值,那么就退出当前循环,然后更新ans。这就用到了贪心的思想。
注意在每次更新ans后都应该给father数组赋初值,因为下一轮的更新与当前的father数组无关。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int const N=210;
const int INF=0x3f3f3f3f;
const int M=1010;
int father[N];
struct node
{
int x,y;
int d;
};
node a[M];
int Find(int x)
{
int y=x;
while(y!=father[y]) y=father[y];
while(father[x]!=y)
{
int tmp=father[x];
father[x]=y;
x=tmp;
}
return y;
}
void Union(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
father[fx]=fy;
}
bool cmp(node a,node b)
{
return a.d<b.d;
}
int main()
{
int m,n;
while(~scanf("%d%d",&m,&n))
{
for(int i=0;i<n;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
sort(a,a+n,cmp);
int v;
scanf("%d",&v);
while(v--)
{
int s,e;
scanf("%d%d",&s,&e);
int ans=INF;
for(int i=0;i<n;i++)
{
for(int k=1;k<=m;k++) father[k]=k; //每次都给father数组赋初值
int tmp=INF;
for(int j=i;j<n;j++)
{
if(Find(a[j].x)!=Find(a[j].y))
{
Union(a[j].x,a[j].y);
if(Find(s)==Find(e)) //一旦发现start和end在同一个集合里,则退出
{
tmp=a[j].d-a[i].d;
//cout<<i<<" "<<j<<" tmp="<<tmp<<endl;
break;
}
}
}
ans=min(ans,tmp); //每次选出最舒适的那个速度差
}
if(ans==INF) printf("-1\n"); //起点和终点之间没有通路
else printf("%d\n",ans);
}
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/Amidgece/p/5742653.html