每日一题 [HAOI2006]旅行 题解
简单题,我们发现边数和点数都很小
允许我们可以用平方做法来做,然后我们直接枚举最小的边权,依次往上最小做生成树,然后把所有得出的答案取个最优就可以了,在这里我们可以把并查集的复杂度看成是O(1)的,因为边数只有500。
具体细节需要我们判断分数的大小和一些无解的情况,看一下代码就ok了
代码:
#include<bits/stdc++.h> #define LL long long using namespace std; const int N=505,M=5e3+5; struct Graph{int u,v,w;}gra[M]; int n,m,s,t,fa[N],fz=-1,fm=-1; int find(int u){return fa[u]==u?u:fa[u]=find(fa[u]);} bool Cmp(int x,int y,int x2,int y2){return (fz==-1&&fm==-1)||x*y2<x2*y;} bool cmp(Graph a,Graph b){return a.w<b.w;} int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d%d%d",&gra[i].u,&gra[i].v,&gra[i].w); scanf("%d%d",&s,&t); sort(gra+1,gra+m+1,cmp); for(int i=1,res,maw;i<=m;i++){ bool fl=false; for(int j=1;j<=n;j++)fa[j]=j; for(int j=i,u,v;j<=m;j++){ u=gra[j].u;v=gra[j].v; if(find(u)!=find(v)){ fa[fa[u]]=fa[v]; if(find(s)==find(t)){maw=gra[j].w;fl=true;break;} } } if(!fl){ if(i==1){puts("IMPOSSIBLE");return 0;} break; } if(Cmp(maw,gra[i].w,fz,fm))fz=maw,fm=gra[i].w; } int g=__gcd(fz,fm);fz/=g;fm/=g; if(fz%fm==0)printf("%d\n",fz/fm);else printf("%d/%d\n",fz,fm); return 0; }