【NOI2014】魔法森林
2016-09-05 20:18
232 查看
Description
给出一张n个点,m条边的图,每条边有两个边权(a,b),求从1到n的路径中所有的权a最大值+权b最大值的最小值是多少。n<=50000,m<=100000
Solution
长得那么像双关键字的最小生成树。不过是最大值的和而已。
那么我们可以把所有的边按a值从小到大排序。
然后依次加边,如果形成了环那么就删去环上b值最大的边。
原因嘛参照kurskal的证明~
我才不会说我不会证
也就是说我们要动态加边,删边,求最大值。
LCT嘛。。。
话说各位说用LCT神犇好像都是用spfa虐过去的啊
Code
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define N 150005 using namespace std; struct note{int x,y,a,b;}a ; bool cmp(note x,note y) {return x.a<y.a;} int t [2],f ,p ,mx ,key ,d ,rev ; int n,m,ans,fa ; int get(int x) {return fa[x]?fa[x]=get(fa[x]):x;} int son(int x) { return t[f[x]][1]==x; } void updata(int x) { int l=t[x][0],r=t[x][1]; if (a[mx[l]].b>a[mx[r]].b) mx[x]=mx[l]; else mx[x]=mx[r]; if (a[key[x]].b>a[mx[x]].b) mx[x]=key[x]; } void down(int x) { if (rev[x]) { rev[x]=0; if (t[x][0]) rev[t[x][0]]^=1; if (t[x][1]) rev[t[x][1]]^=1; swap(t[x][0],t[x][1]); } } int remove(int x,int y) { do { d[++d[0]]=x;x=f[x]; } while (x!=y); while (d[0]) down(d[d[0]--]); } void rotate(int x) { int y=f[x],z=son(x);f[x]=f[y]; if (f[x]) t[f[x]][son(y)]=x; else p[x]=p[y],p[y]=0; if (t[x][1-z]) f[t[x][1-z]]=y; f[y]=x;t[y][z]=t[x][1-z];t[x][1-z]=y; updata(y);updata(x); } void splay(int x,int y) { remove(x,y); while (f[x]!=y) { if (f[f[x]]!=y) if (son(x)==son(f[x])) rotate(f[x]); else rotate(x); rotate(x); } } void access(int x) { int y=0; while (x) { splay(x,0); f[t[x][1]]=0;p[t[x][1]]=x; t[x][1]=y;p[y]=0;f[y]=x; updata(x);y=x;x=p[x]; } } void makeroot(int x) { access(x);splay(x,0);rev[x]^=1; } void link(int x,int y) { makeroot(x);p[x]=y; } void cut(int x,int y) { makeroot(x);access(y);splay(y,0); t[y][0]=0;p[x]=f[x]=0; updata(y); } int find(int x,int y) { makeroot(x);access(y);splay(y,0); return mx[y]; } int main() { scanf("%d%d",&n,&m); fo(i,1,m) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b),key[i+n]=i; sort(a+1,a+m+1,cmp);ans=0x7fffffff; fo(i,1,m) { if (a[i].x==a[i].y) continue; int ax=get(a[i].x),by=get(a[i].y); if (ax==by) { int l=find(a[i].x,a[i].y); if (a[l].b>a[i].b) { cut(a[l].x,l+n);cut(a[l].y,l+n); link(a[i].x,i+n);link(a[i].y,i+n); } } else { fa[by]=ax; link(a[i].x,i+n);link(a[i].y,i+n); } ax=get(1);by=get(n); if (ax==by) ans=min(ans,a[i].a+a[find(1,n)].b); } if (ans==0x7fffffff) printf("-1");else printf("%d",ans); }
相关文章推荐
- NOI2014 魔法森林 LCT维护MST
- [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集
- [题解]bzoj3669(NOI2014)魔法森林
- NOI 2014 魔法森林
- 【NOI2014】魔法森林
- BZOJ 3669 [Noi2014]魔法森林 LCT
- 神spfa [Noi2014]魔法森林
- NOI2014魔法森林题解报告
- [BZOJ3669][Noi2014]魔法森林(动态spfa)
- bzoj3669 [Noi2014]魔法森林
- cogs1685 【NOI2014】魔法森林 Link-Cut Tree
- 3669 [Noi2014]魔法森林(LCT,最小生成树)
- [Noi2014]魔法森林 (Link Cut Tree)
- bzoj 3669: [Noi2014]魔法森林 link cut tree
- NOI2014魔法森林题解报告
- bzoj 3669: [Noi2014]魔法森林 -- 动点spfa
- 3669: [Noi2014]魔法森林 LCT
- 【BZOJ 3669】 3669: [Noi2014]魔法森林 (动态spfa)
- 【NOI2014】bzoj3669 魔法森林
- [NOI2014]魔法森林