[最小极差生成树 LCT || 二分答案 CDQ分治 并查集] Ural 2055 Urban Geography
2017-03-04 09:28
495 查看
把边按权值大小排序
然后用LCT按时间维护下最大生成树
就好了
还有浅显易懂的二分答案 然后 cdq分治加并查集维护连通性
三个log 略慢
然后用LCT按时间维护下最大生成树
就好了
#include<cstdio> #include<cstdlib> #include<algorithm> #include<stack> #include<set> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; int u ,v ,w ; inline int Min(int a,int b){ return w[a]<w[b]?a:b; } struct node{ node *ch[2],*f; int v,idx; bool rev; bool isr() { return !f || (f->ch[0]!=this && f->ch[1]!=this); } bool dir() { return f->ch[1]==this; } void setc(node *c,int d){ ch[d]=c; if (c) c->f=this; } void push(){ if (rev) { swap(ch[0],ch[1]); if(ch[0])ch[0]->rev^=1; if(ch[1])ch[1]->rev^=1; rev=0; } } void upd(){ v=idx; if(ch[0])v=Min(v,ch[0]->v); if(ch[1])v=Min(v,ch[1]->v); } }pool ; inline void rot(node *x){ node *p=x->f; bool d=x->dir(); if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f; p->setc(x->ch[d^1],d); x->setc(p,d^1); p->upd(); } stack<node*> sta; inline void splay(node *x){ node *q=x; for (;!q->isr();q=q->f) sta.push(q); sta.push(q); while (!sta.empty()) sta.top()->push(),sta.pop(); while (!x->isr()) if (x->f->isr()) rot(x); else if (x->dir()==x->f->dir()) rot(x->f),rot(x); else rot(x),rot(x); x->upd(); } inline void expose(node *x){ for (node *q=NULL;x;q=x,x=x->f) splay(x),x->ch[1]=q,x->upd(); } inline void exert(node *x){ expose(x); splay(x); x->rev^=1; } inline void link(node *x,node *y) { exert(x); x->f=y; } inline void cut(node *x,node *y) { exert(y); expose(x); splay(x); x->ch[0]=y->f=NULL; x->upd(); } node *frt(node *x){ expose(x),splay(x); for (;x->push(),x->ch[0];x=x->ch[0]); return x; } inline int query(node *x,node *y) { exert(y); expose(x); splay(x); return x->v; } struct edge{ int u,v,w,idx; bool operator < (const edge & B) const{ return w<B.w; } }ed ; set<int> Set; int n,m; int al,ar; int fat ; inline int Fat(int u){ return u==fat[u]?u:fat[u]=Fat(fat[u]); } inline bool Merge(int x,int y){ x=Fat(x); y=Fat(y); if (x==y) return 0; fat[x]=y; return 1; } int lst ,pnt; int Ans=1<<30; int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); for (int i=1;i<=m;i++) read(ed[i].u),read(ed[i].v),read(ed[i].w),ed[i].idx=i; sort(ed+1,ed+m+1); for (int i=1;i<=m;i++) u[i]=ed[i].u,v[i]=ed[i].v,w[i]=ed[i].w,pool[i].idx=pool[i].v=i; for (int i=m+1;i<=m+n;i++) pool[i].idx=pool[i].v=i,w[i]=1<<30; for (int i=1;i<=m;i++){ int u=::u[i],v=::v[i]; if (frt(pool+m+u)==frt(pool+m+v)){ int t=query(pool+m+u,pool+m+v); if (w[t]<w[i]){ cut(pool+m+::u[t],pool+t),cut(pool+m+::v[t],pool+t); Set.erase(t); link(pool+m+u,pool+i),link(pool+m+v,pool+i); Set.insert(i); } }else link(pool+m+u,pool+i),link(pool+m+v,pool+i),Set.insert(i); if (Set.size()==n-1){ int l=*Set.begin(),r=*Set.rbegin(); if (w[r]-w[l]<Ans) Ans=w[r]-w[l],al=l,ar=r; } } for (int i=1;i<=n;i++) fat[i]=i; for (int i=al;i<=ar;i++) if (Merge(ed[i].u,ed[i].v)) lst[++pnt]=ed[i].idx; sort(lst+1,lst+pnt+1); for (int i=1;i<=pnt;i++) printf("%d ",lst[i]); printf("\n"); return 0; }
还有浅显易懂的二分答案 然后 cdq分治加并查集维护连通性
三个log 略慢
#include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> #define pb push_back using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; int fat ,rnk ; int Tot; int pnt,sx ,sy ,rx ; inline void init(int n){ for (int i=1;i<=n;i++) fat[i]=i,rnk[i]=0; pnt=0; Tot=n; } inline int Fat(int u){ return u==fat[u]?u:Fat(fat[u]); } inline bool Merge(int x,int y){ x=Fat(x),y=Fat(y); if (x==y) return 0; if (rnk[x]<rnk[y]) swap(x,y); sx[++pnt]=x; sy[pnt]=y; rx[pnt]=rnk[x]; Tot--; fat[y]=x; if (rnk[x]==rnk[y]) rnk[x]++; return 1; } inline void Back(int bot){ while (pnt>bot){ fat[sy[pnt]]=sy[pnt]; rnk[sx[pnt]]=rx[pnt]; pnt--; Tot++; } } struct edge{ int u,v,w,idx; void read(int i) {::read(u); ::read(v); ::read(w); idx=i; } bool operator < (const edge &B) const{ return w<B.w; } }ed ; int u ,v ,w ; struct info{ int i,l,r; info(int i,int l,int r):i(i),l(l),r(r) { } }; int End; inline bool Solve(int l,int r,vector<info> &v0){ int bot=pnt,mid=(l+r)>>1; vector<info> v1,v2; for (int i=0;i<(int)v0.size();i++) if (v0[i].l<=l && r<=v0[i].r) Merge(u[v0[i].i],v[v0[i].i]); else{ if (v0[i].l<=mid) v1.pb(v0[i]); if (v0[i].r>mid) v2.pb(v0[i]); } if (l==r) { if (Tot==1) End=l; int tmp=Tot; Back(bot); return tmp==1; } int ret=Solve(l,mid,v1) || Solve(mid+1,r,v2); Back(bot); return ret; } int n,m; inline bool check(int x){ init(n); vector<info> v0; for (int i=1;i<=m;i++) v0.pb(info(i,i,upper_bound(w+1,w+m+1,w[i]+x)-w-1)); return Solve(1,m,v0); } int lst ,Pnt; int main(){ freopen("t.in","r",stdin); freopen("t1.out","w",stdout); read(n); read(m); for (int i=1;i<=m;i++) ed[i].read(i); sort(ed+1,ed+m+1); for (int i=1;i<=m;i++) u[i]=ed[i].u,v[i]=ed[i].v,w[i]=ed[i].w; int L=-1,R=w[m]-w[1]+1,MID; while (L+1<R) if (check(MID=(L+R)>>1)) R=MID; else L=MID; int al,ar; ar=End; al=lower_bound(w+1,w+m+1,w[ar]-R)-w; init(n); for (int i=al;i<=ar;i++) if (Merge(ed[i].u,ed[i].v)) lst[++Pnt]=ed[i].idx; sort(lst+1,lst+Pnt+1); for (int i=1;i<=Pnt;i++) printf("%d ",lst[i]); printf("\n"); return 0; }
相关文章推荐
- [LCT维护最小生成树 || CDQ分治 || 线段树 并查集 dfs树] Codeforces 603E #334 (Div. 1) E. Pastoral Oddities
- URAL 2055 Urban Geography 分治,并查集
- BZOJ 2654 tree(二分答案+最小生成树)
- Luogu P1396 营救【最小生成树/二分答案/最短路】 By celur925
- [动态最小生成树 CDQ分治] SnackDown 2017 Online Elimination Round #GQUERY Game Revisited
- [SCU 4525] meixiuxiu学图论 (二分答案 | 最小生成树)
- bzoj2654 Tree 二分答案+最小生成树
- 修公路 最小生成树 二分答案
- BZOJ 4025|二分图|CDQ分治|并查集|LCT
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- <二分答案加验证||最小生成树>bzoj 1821 部落划分
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- 洛谷Oj-P2330 [SCOI2005]繁忙的都市-最小生成树+二分答案
- bzoj2654 二分答案+最小生成树
- 最小生成树 || ( BFS && 二分答案) —— 营救
- [CDQ分治 并查集 || LCT] BZOJ 4025 二分图
- 最小比例生成树(01分数规划)二分或迭代
- hdu1102 Constructing Roads 基础最小生成树(并查集)
- 并查集-用并查集判断图中是否有环(能够应用到kruskal的最小生成树)
- HDU1879 并查集和最小生成树