BZOJ1050 旅行comf

mac2022-06-30  130

目录

BZOJ1050 旅行comf题解code

BZOJ1050 旅行comf

题目传送门

题解

比较妙的一道题。刚开始看到题的时候,感觉可能是两个二分,但是发现这样找到的答案不一定是最优的。然后发现他的边只有5000条,所以我们将边按权值从小到大排序,枚举每一条边,让这条边作为最小的那条边(即只枚举边权比它大的边),跑最小生成树,这样就可以得到一个合法的对于当前情况最优的答案,然后每次更新答案就行了。

code

#include <bits/stdc++.h> using namespace std; typedef long long ll; bool Finish_read; template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x+'0');} template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');} template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);} /*================Header Template==============*/ #define PAUSE printf("Press Enter key to continue..."); fgetc(stdin); const int M=5005; const int N=505; int n,m,s,t; int ansA,ansB; struct edge { int f,t,w; bool operator < (const edge &rhs) const { return w<rhs.w; } }E[M]; int fa[N]; /*==================Define Area================*/ void init() { for(int i=1;i<=n;i++) fa[i]=i; } int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void unite(int x,int y) { x=find(x);y=find(y); if(x==y) return ; fa[x]=y; return ; } int Gcd(int x,int y) { if(!y) return x; else return Gcd(y,x%y); } int main() { read(n);read(m); for(int i=1;i<=m;i++) { read(E[i].f);read(E[i].t);read(E[i].w); } read(s);read(t); sort(E+1,E+1+m); for(int i=1;i<=m;i++) { init(); int tmp=i; while(tmp<=m&&find(s)!=find(t)) { unite(E[tmp].f,E[tmp].t); tmp++; } tmp--; if(find(s)!=find(t)) continue ; if(!ansA||E[tmp].w*1.0/E[i].w<ansA*1.0/ansB) { ansA=E[tmp].w; ansB=E[i].w; } } if(!ansA) return puts("IMPOSSIBLE"),0; if(!(ansA%ansB)) printf("%d\n",ansA/ansB); else { int G=Gcd(ansA,ansB); printf("%d/%d\n",ansA/G,ansB/G); } return 0; }

转载于:https://www.cnblogs.com/Apocrypha/p/9432979.html

最新回复(0)