是一道并查集的好题啊,,,写了一天,总算写出来了。上午用dfs写了一上午,wa了一上午。。。。。。下午又去听了个神马报告,,,直到现在才写出来。。需要深入思考啊,对并查集又了解的深了。 题目是中文的,意思很简单。下面说下思路。
题目要求从起点到终点的最大值和最小值的差的最小值。因此,可以先将所有边排序,之后对每条边两重循环,不断加入边,并随时判断起点和终点是不是连同的,这就要用到并查集,用并查集判断随时判断是否连通,当连通时,说明此时从起点到终点有一条可达路径,求差即可。并随时与最小值比较即可。
4 4 1 2 2 2 3 4 1 4 1 3 4 2 2 1 3 1 2
1 0
#include <iostream> #include <string.h> #include <cstdio> #include <algorithm> using namespace std; struct point{ int lp,rp,value; }pp[1005]; int father[205]; bool cmp(point a,point b){ return a.value<b.value; } void init(){ for(int i=0;i<204;++i) father[i]=i; } int find(int x){ if(x==father[x]) return x; else father[x]=find(father[x]); } void unionset(int x,int y){ int rootx=find(x); int rooty=find(y); if(rootx!=rooty) father[rooty]=rootx; } int main(){ //freopen("1.txt","r",stdin); int numcity,numroad; while(~scanf("%d%d",&numcity,&numroad)){ for(int i=0;i<numroad;++i){ scanf("%d%d%d",&pp[i].lp,&pp[i].rp,&pp[i].value); } sort(pp,pp+numroad,cmp); int numask; scanf("%d",&numask); int a,b,i,j,mmin,ans; while(numask--){ scanf("%d%d",&a,&b); mmin=100000000; for(i=numroad-1;i>=0;--i){ init(); ans=mmin; for(j=i;j>=0;--j){ unionset(pp[j].lp,pp[j].rp); int roota=find(a); int rootb=find(b); if(roota==rootb){ ans=pp[i].value-pp[j].value; break; } } if(mmin>ans) mmin=ans; } if(mmin==100000000)mmin=-1; printf("%d\n",mmin); } } return 0; }