BZOJ 3669: [Noi2014]魔法森林
2017-05-18 19:32
387 查看
题目
BZOJ 3669: [Noi2014]魔法森林题解
感觉收获就是get了一种除了Kruskal和prim之外的最小生成树算法。理论复杂度貌似是mlogn,不过常数巨大堪比一个log(此句话引用自某论文)。
陈年老题谁都会做,我没做出来qwq。边权按a排序之后做b的最小生成树。对于一条连接(u,v)的边,如果uv不连通那么连起来,否则找u->v最大的边权,然后切掉,把当前边加进去,当1,n联通的时候可以更新答案(我tm还zz的写成了弄出来一棵生成树的时候才有答案,好像也有很多人和我一样(雾))。边权不好维护,把边抽象成点,用点权维护。
然后就是splay维护最大值和最大值出现位置了。easy。感觉lct的板子总是哪里要打错然后调很久233,。不过调的越来越熟练了。自己发明了一套成体系的调试方法,对于指针党简直是太棒了。
代码
//QWsin #include<map> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=200000+10; const int maxm=100000+10; map<int,int>id; int n,m; struct Edge { int u,v,a,b; inline void input(){scanf("%d%d%d%d",&u,&v,&a,&b);} inline bool operator < (const Edge &rhs)const{ return a<rhs.a||(a==rhs.a&&b<rhs.b); } } e[maxm]; struct Node { int v,pos,mx,posx,rev; Node *ch[2],*fa; Node(){v=pos=mx=posx=rev=0;ch[0]=ch[1]=fa=NULL;} Node(int v,int pos):v(v),pos(pos){mx=v,posx=pos;rev=0;ch[0]=ch[1]=fa=NULL;} inline 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; } } inline void up() { mx=v,posx=pos; if(ch[0] && ch[0]->mx > mx) mx=ch[0]->mx,posx=ch[0]->posx; if(ch[1] && ch[1]->mx > mx) mx=ch[1]->mx,posx=ch[1]->posx; }; inline void out(){ if(!this) {puts("NULL");return ;} printf("%d:\n",id[(int)this]); printf(" ch[0]=%d\n",id[(int)ch[0]]); printf(" ch[1]=%d\n",id[(int)ch[1]]); printf(" fa=%d\n",id[(int)fa]); printf(" val=%d\n",v); printf(" mx=%d\n",mx); printf(" posx=%d\n",posx); puts("\n"); } }*tmp[maxn]; struct LinkCutTree { Node *node[maxn]; inline void init() { id[0]=0; for(int i=1; i<=n; ++i) node[i]=new Node(),id[(int)node[i]]=i; for(int i=1; i<=m; ++i) node[n+i]=new Node(e[i].b,i),id[(int)node[n+i]]=n+i; } inline int pd(Node* p){return p->fa->ch[1]==p;} inline int is_root(Node* p){return (!(p->fa))||(p->fa->ch[0]!=p&&p->fa->ch[1]!=p);} inline void rotate(Node* p) { int c=pd(p)^1; Node *t=p->fa; t->ch[c^1]=p->ch[c]; if(p->ch[c]) p->ch[c]->fa=t; p->fa=t->fa; if(!is_root(t)) p->fa->ch[pd(t)]=p; t->fa=p;p->ch[c]=t;t->up();p->up(); // p->out(); } inline void splay(Node *p) { int top=0; for(Node* t=p;; t=t->fa) { tmp[++top]=t; if(is_root(t)) break; } for(; top>=1; --top) tmp[top]->push(); for(; !is_root(p); rotate(p)) if(!is_root(p->fa)) rotate(pd(p)==pd(p->fa) ? p->fa:p); } inline void access(Node* p) { // p->out(); for(Node* pre=NULL; p ; pre=p,p=p->fa){ splay(p),p->ch[1]=pre,p->up(); // pre->out();p->out(); } } inline void make_root(Node* p){access(p);splay(p);p->rev=1;} inline void link(Node* a,Node *b){ // a->out();b->out(); make_root(a);a->fa=b; // a->out();b->out(); } inline void cut(Node* a,Node *b){ make_root(a);access(b);splay(b); a->fa=b->ch[1]=NULL;b->up(); } inline void link(int i){ link(node[e[i].u],node[n+i]); link(node[n+i],node[e[i].v]); } inline void cut(int i){ cut(node[e[i].u],node[i+n]); cut(node[i+n],node[e[i].v]); } inline int getmx(int u,int v,int &id) //u->v路径最大值 { make_root(node[v]); access(node[u]); splay(node[u]); id=node[u]->posx; return node[u]->mx; } //在u->v路径上找到最大的决定要不要换 inline void find_mx(int i) { int id,val=getmx(e[i].u,e[i].v,id); if(val > e[i].b){cut(id);link(i);} } } lct; inline void init_data() { cin>>n>>m; for(int i=1; i<=m; ++i) e[i].input(); sort(e+1,e+m+1); } int p[maxn]; int findset(int x){return p[x]==x?x:p[x]=findset(p[x]);} inline void solve() { for(int i=1; i<=n; ++i) p[i]=i; lct.init(); int ans=1<<30,cnt=n,bin; for(int i=1; i<=m; ++i) { if(e[i].a > ans) break; int u=e[i].u,v=e[i].v; u=findset(u); v=findset(v); if(u!=v){lct.link(i); p[u]=v; --cnt;} else lct.find_mx(i); if(findset(1)==findset(n)) ans=min(ans,e[i].a+lct.getmx(1,n,bin)); } if(findset(1)!=findset(n)) puts("-1"); else cout<<ans<<endl; } int main() { init_data(); solve(); return 0; }
相关文章推荐
- BZOJ 3669: [Noi2014]魔法森林
- [bzoj3669][NOI2014]魔法森林
- BZOJ 3669 [Noi2014]魔法森林 LCT
- bzoj3669: [Noi2014]魔法森林
- [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集
- [BZOJ3669][NOI2014]魔法森林(LCT)
- bzoj 3669: [Noi2014]魔法森林
- [bzoj3669][Noi2014]魔法森林——lct
- BZOJ 3669 [Noi2014]魔法森林(贪心+LCT)
- BZOJ 3669 . JZOJ 3754. 【NOI2014】魔法森林
- bzoj 3669: [Noi2014]魔法森林
- [BZOJ]3669: [Noi2014]魔法森林 lct
- 【BZOJ3669】[Noi2014]魔法森林 LCT
- 【NOI2014】bzoj3669 魔法森林
- BZOJ3669 [Noi2014]魔法森林
- [BZOJ3669][UOJ#3][Noi2014][LCT]魔法森林
- BZOJ 3669: [Noi2014]魔法森林( LCT )
- 【BZOJ3669】NOI2014-魔法森林(神奇的解法)
- 【BZOJ 3669】 3669: [Noi2014]魔法森林 (动态spfa)
- bzoj 3669: [Noi2014]魔法森林 link cut tree