P2502 [HAOI2006]旅行——暴力和并查集的完美结合
P2502 [HAOI2006]旅行
一定要看清题目数据范围再决定用什么算法,我只看着是一个蓝题就想到了记录最短路径+最小生成树,但是我被绕进去了;
看到只有5000的边,我们完全可以枚举最小边和最大边,判断起点和终点是否连通用并查集维护一下就好了;
分数约分一定要仔细想想,
an1==ans2的时候我直接printf("%d",ans1)了,(劝退到小学)
gcd自己写一个吧,(图省事用__gcd()在洛谷水一水也不是不可以吧)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=5010; 6 struct node 7 { 8 int x,y,z; 9 10 bool operator < (const node &we)const 11 { 12 return z<we.z; 13 } 14 }f[maxn]; 15 16 int n,m; 17 18 int father[maxn]; 19 20 int getfather(int x) 21 { 22 if(father[x]==x) return x; 23 father[x]=getfather(father[x]); 24 return father[x]; 25 } 26 27 void merging(int x,int y) 28 { 29 father[getfather(x)]=getfather(y); 30 } 31 32 int s,t; 33 34 double ans=1e9; 35 36 int ans1,ans2; 37 38 int gcd(int a,int b) 39 { 40 return b==0?a:gcd(b,a%b); 41 } 42 43 int main() 44 { 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=n;i++) father[i]=i; 47 for(int i=1;i<=m;i++) 48 { 49 scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z); 50 merging(f[i].x,f[i].y); 51 } 52 53 scanf("%d%d",&s,&t); 54 55 if(getfather(s)!=getfather(t)) 56 { 57 printf("IMPOSSIBLE\n"); 58 return 0; 59 } 60 sort(f+1,f+m+1); 61 for(int i=1;i<=m;i++) 62 { 63 for(int k=1;k<=n;k++) father[k]=k; 64 for(int j=i;j<=m;j++) 65 { 66 merging(f[j].x,f[j].y); 67 if(getfather(s)==getfather(t)) 68 { 69 double qw=(double)f[j].z/(double)f[i].z; 70 if(qw<ans) 71 { 72 ans=qw; 73 ans1=f[j].z;ans2=f[i].z; 74 } 75 break; 76 } 77 } 78 } 79 80 if(ans1==ans2) 81 { 82 printf("1"); 83 } 84 else 85 { 86 int we=gcd(ans1,ans2); 87 if(ans2/we==1) printf("%d",ans1/we); 88 else printf("%d/%d\n",ans1/we,ans2/we); 89 } 90 return 0; 91 }