hdu 1598 第一道并查集
虽然在学数据结构的时候看过并查集。。。好像是在Kruskal算法中讲到了,不过做题中用到这还是头一次。。。哎,acm有太多的第一次了。。。不过生命不休,学习不止。。。
好吧。。。不多说了。。。
View Code
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 }