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 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值