BZOJ1050 HAOI2006旅行(最小生成树+动态树)
暴力枚举路径中权值最小边是哪个,然后求出边权不小于它的边的最小生成树,即可保证该路径上最大值最小。暴力当然可以过,这里使用LCT维护。注意数据中有自环。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 510 #define M 5010 #define lson tree[k].ch[0] #define rson tree[k].ch[1] #define lself tree[tree[k].fa].ch[0] #define rself tree[tree[k].fa].ch[1] int n,m,s,t,ansx,ansy,v[N+M]; struct edge { int x,y,z; bool operator <(const edge&a) const { return z<a.z; } }e[M]; struct data{int ch[2],fa,rev,x; }tree[N+M]; void up(int k) { tree[k].x=k; if (v[tree[lson].x]>v[tree[k].x]) tree[k].x=tree[lson].x; if (v[tree[rson].x]>v[tree[k].x]) tree[k].x=tree[rson].x; } void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;} void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;} bool isroot(int k){return lself!=k&&rself!=k;} int whichson(int k){return rself==k;} void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);} void move(int k) { int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k); if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf; tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa; tree[fa].fa=k,tree[k].ch[!p]=fa; up(fa),up(k); } void splay(int k) { push(k); while (!isroot(k)) { int fa=tree[k].fa; if (!isroot(fa)) if (whichson(k)^whichson(fa)) move(k); else move(fa); move(k); } } void access(int k){for (int t=0;k;t=k,k=tree[k].fa) splay(k),tree[k].ch[1]=t,up(k);} void makeroot(int k){access(k),splay(k),rev(k);} int findroot(int k){access(k),splay(k);for (;lson;k=lson) down(k);splay(k);return k;} void link(int x,int y){makeroot(x);tree[x].fa=y;} void cut(int x,int y){makeroot(x);access(y);splay(y);tree[y].ch[0]=tree[x].fa=0;up(y);} int query(int x,int y){makeroot(x);access(y);splay(y);return tree[y].x;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int main() { #ifndef ONLINE_JUDGE freopen("bzoj1050.in","r",stdin); freopen("bzoj1050.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); for (int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read(); s=read(),t=read(); sort(e+1,e+m+1); ansx=1000000000,ansy=1; for (int i=1;i<=n;i++) v[i]=-1; for (int i=1;i<=m;i++) v[i+n]=e[i].z; for (int i=m;i;i--) if (e[i].x!=e[i].y) { if (findroot(e[i].x)==findroot(e[i].y)) { int x=query(e[i].x,e[i].y); cut(x,e[x-n].x),cut(x,e[x-n].y); } link(i+n,e[i].x),link(i+n,e[i].y); if (findroot(s)==findroot(t)) { int x=v[query(s,t)]; if (1ll*x*ansy<1ll*ansx*e[i].z) ansx=x,ansy=e[i].z; } } if (ansx==1000000000) cout<<"IMPOSSIBLE"; else if (ansx%ansy==0) cout<<ansx/ansy; else cout<<ansx/gcd(ansx,ansy)<<'/'<<ansy/gcd(ansx,ansy); return 0; }
- bzoj 1050 [HAOI2006]旅行comf (最小生成树)
- 【bzoj1050】 HAOI2006旅行comf 最小生成树
- bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)
- 【BZOJ 1050】 【HAOI 2006】旅行comf(最小生成树枚举)
- bzoj 1050 [HAOI2006]旅行comf [最小生成树] [动点spfa] [LCT]
- [BZOJ1050]HAOI2007旅行|最小生成树|枚举
- BZOJ 1050 HAOI 2006 旅行comf SPFA动态加点
- 【BZOJ 1050】1050: [HAOI2006]旅行comf (动态SPFA)
- [bzoj1050] [HAOI2006]旅行comf
- [并查集]BZOJ 1050——[HAOI2006]旅行comf
- 【bzoj 1050】 [HAOI2006]旅行comf
- BZOJ 1050: [HAOI2006]旅行comf 贪心,并查集
- bzoj 1050: [HAOI2006]旅行comf
- BZOJ 1050 [HAOI2006]旅行comf
- [BZOJ 1050] HAOI 2006 旅行comf · Kruskal
- bzoj1050: [HAOI2006]旅行comf(最小生成树)
- 【BZOJ】1050 [HAOI2006]旅行comf 并查集
- [BZOJ1050][HAOI2006]旅行comf(图论)
- 【bzoj1050】[HAOI2006]旅行comf
- BZOJ 1050 [HAOI2006]旅行comf Kruskal