首页 > 代码库 > BZOJ 1050 旅行(并查集)
BZOJ 1050 旅行(并查集)
很好的一道题。
首先注意,要使的s到t的路径上最大边/最小边的值最小。我们可以尝试一下二分并验证答案。
但是不能二分最大边/最小边。 我们可以二分 最小边的权值。于是算法就出来了。
首先把边权排序。然后枚举最小的边,再依次添加不小于该边的边,直到s和t联通。用并查集维护即可。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-3 # define MOD 998244353 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back # define set pabs typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())==‘-‘) flag=1; else if(ch>=‘0‘&&ch<=‘9‘) res=ch-‘0‘; while((ch=getchar())>=‘0‘&&ch<=‘9‘) res=res*10+(ch-‘0‘); return flag?-res:res; } void Out(int a) { if(a<0) {putchar(‘-‘); a=-a;} if(a>=10) Out(a/10); putchar(a%10+‘0‘); } const int N=505; //Code begin... typedef struct{int u, v, w;}Node; Node edge[5005]; int fa[N]; bool comp(Node a, Node b){return a.w<b.w;} int find(int x) { int s, temp; for (s=x; fa[s]>=0; s=fa[s]) ; while (s!=x) temp=fa[x], fa[x]=s, x=temp; return s; } void union_set(int x, int y) { int temp=fa[x]+fa[y]; if (fa[x]>fa[y]) fa[x]=y, fa[y]=temp; else fa[y]=x, fa[x]=temp; } int gcd(int x, int y){return y?gcd(y,x%y):x;} int main () { int n, m, u, v, mi, ma, s, t, ans[2]; double answer=INF; scanf("%d%d",&n,&m); FOR(i,1,m) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); scanf("%d%d",&s,&t); sort(edge+1,edge+m+1,comp); FOR(i,1,m) { mem(fa,-1); mi=edge[i].w; ma=0; FOR(j,i,m) { u=edge[j].u, v=edge[j].v; if (find(u)!=find(v)) union_set(find(u),find(v)); if (find(s)==find(t)) {ma=edge[j].w; break;} } if (ma) if (answer>(double)ma/mi) answer=(double)ma/mi, ans[0]=ma/gcd(ma,mi), ans[1]=mi/gcd(ma,mi); } if (fabs(answer-INF)<eps) puts("IMPOSSIBLE"); else { if (ans[1]==1) printf("%d\n",ans[0]); else printf("%d/%d\n",ans[0],ans[1]); } return 0; }
BZOJ 1050 旅行(并查集)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。