雖然在學數據結構的時候看過並查集。。。好像是在Kruskal算法中講到了,不過做題中用到這還是頭一次。。。哎,acm有太多的第一次了。。。不過生命不休,學習不止。。。
好吧。。。不多說了。。。

1 #include<iostream> 2 #include<algorithm> 3 const int N=1010; 4 const int inf=1000000; 5 using namespace std; 6 7 struct Road{ 8 int st,ed,pd; //起點,終點、速度 9 }; 10 11 int cmp(const Road &p,const Road &q){ 12 return p.pd<q.pd; 13 } 14 15 int parent[N]; 16 int n,m; 17 18 //初始化 19 void UFset(){ 20 for(int i=1;i<=n;i++){ 21 parent[i]=-1; 22 } 23 } 24 //查找並返回x所屬集合的根結點 25 int Find(int x){ 26 int s; 27 for(s=x;parent[s]>=0;s=parent[s]); //一直查到parent[s]為負數(此時s為根結點)為止 28 //路徑壓縮,優化,便於后續的查找操作加速 29 while(s!=x){ 30 int temp=parent[x]; 31 parent[x]=s; 32 x=temp; 33 } 34 return s; 35 } 36 //R1、R2是兩個元素,屬於不同的集合,現在合並這兩個集合 37 void Union(int R1,int R2){ 38 int r1=Find(R1); //r1為R1的根結點 39 int r2=Find(R2); //r2為R2的根結點 40 //路徑為r1->r2,因此根結點r2所在的樹作為r1的子樹 41 if(r1!=r2){ 42 parent[r2]=r1; 43 } 44 } 45 46 int main(){ 47 while(scanf("%d%d",&n,&m)!=EOF){ 48 Road road[N]; 49 for(int i=1;i<=m;i++){ 50 scanf("%d%d%d",&road[i].st,&road[i].ed,&road[i].pd); 51 } 52 // sort(road,road+m,cmp);orz//////就是在這兒被坑了好久,我是從1開始的,排序的時候當然得從road[1]開始了。。。。。。教訓那。。。orz 53 sort(road+1,road+1+m,cmp); 54 int _case; 55 scanf("%d",&_case); 56 while(_case--){ 57 int st,ed; 58 int min=inf; 59 scanf("%d%d",&st,&ed); 60 for(int i=1;i<=m;i++){ 61 UFset(); 62 for(int j=i;j<=m;j++){ 63 Union(road[j].st,road[j].ed); //進行合並 64 //如果在同一集合中、、、 65 if(Find(st)==Find(ed)){ 66 int ans=road[j].pd-road[i].pd; //舒適度吧 67 if(ans<min) 68 min=ans; 69 break; 70 } 71 } 72 } 73 if(min==inf){ 74 printf("-1\n"); 75 }else 76 printf("%d\n",min); 77 } 78 } 79 return 0; 80 }