[NOI2014]魔法森林

题解:

lct维护生成树

首先先把a按照权值从小到大排序

然后维护路径间b的最小值(其实就是满足树的性质)

如果这两点之间连边了,我们就找到其中的最大边,判断一下他和当前点的大小关系

边权变成点权处理就可以了

代码:

 

#include <bits/stdc++.h>
using namespace std;
#define N 200000
struct re{
  int a,b,c,d;
}a[N*2];
int v[N],data[N],data2[N],n,m;
int leftson[N],rightson[N],fa[N];
bool rev[N];
bool cmp(re x,re y)
{
  return(x.c<y.c);
}
void updata(int x)
{
  data[x]=max(max(data[leftson[x]],data[rightson[x]]),v[x]);
  if (data[x]==v[x]) data2[x]=x;
  else if (data[x]==data[leftson[x]]) data2[x]=data2[leftson[x]];
  else data2[x]=data2[rightson[x]];
}
void down(int x)
{
  if (!rev[x]) return;
  swap(leftson[x],rightson[x]); rev[x]=0;
  rev[leftson[x]]^=1; rev[rightson[x]]^=1;
}
bool pd(int x)
{
  if (leftson[fa[x]]!=x&&rightson[fa[x]]!=x) return(0);
  else return(1);
}
void rotate(int x,int y)
{
  int father=fa[x];
  if (y==1)
  {
     rightson[father]=leftson[x];
     if (leftson[x]) fa[leftson[x]]=father;
  } else
  {
     leftson[father]=rightson[x];
     if (rightson[x]) fa[rightson[x]]=father;       
  }
  fa[x]=fa[father];
  if (pd(father))
  {
    if (leftson[fa[x]]==father) leftson[fa[x]]=x;
      else rightson[fa[x]]=x; 
  }
  if (y==1) leftson[x]=father;
  else rightson[x]=father;
  fa[father]=x;
  updata(father); updata(x);
}
void dfs(int x)
{
  if (pd(x)) dfs(fa[x]);
  down(x);
}
void splay(int x)
{
  dfs(x);
  int father=fa[x];
  while (pd(x))
  {
     if (!pd(father))
     {
       if (x==leftson[father]) rotate(x,2);
       else rotate(x,1);
     } else
     {
       if (father==leftson[fa[father]])
         if (x==leftson[father])
           rotate(father,2),rotate(x,2);
         else rotate(x,1),rotate(x,2);
       else 
         if (x==rightson[father])
           rotate(father,1),rotate(x,1);
         else rotate(x,2),rotate(x,1);
     }
     father=fa[x];
  }
}
void access(int x)
{
  for (int y=0;x;y=x,x=fa[x])
    splay(x),rightson[x]=y,updata(x);
}
void makeroot(int x)
{
  access(x);
  splay(x);
  rev[x]^=1;
}
int findroot(int x)
{
  access(x);
  splay(x);
  while (leftson[x]) x=leftson[x];
  return x;
}
void split(int x,int y)
{
  makeroot(x);
  access(y);
  splay(y);
}
bool find(int x,int y)
{
  makeroot(x);
  if (findroot(y)!=x) return(0);
  else return(1);
}
void link(int x,int y)
{
  makeroot(x);
  if (findroot(y)!=x) fa[x]=y;
}
void cut(int x,int y)
{
  makeroot(x);
  if (findroot(y)==x&&fa[x]==y&&!rightson[x])
  {  
    fa[x]=leftson[y]=0;
    updata(y);
  }
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=m;i++)
      cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d;
    sort(a+1,a+m+1,cmp);
    int ans=1e9;
    for (int i=1;i<=m;i++)
    {
      int x=a[i].a,y=a[i].b;
      if (find(a[i].a,a[i].b))
      {
        split(x,y);
        int tmp=data2[y];
        if (a[i].d<data[y])
        {
          cut(tmp,a[tmp-n].a);
          cut(tmp,a[tmp-n].b);
          link(i+n,a[i].a);
          link(i+n,a[i].b);
          v[i+n]=a[i].d;
        }
      } else
      { 
        link(i+n,a[i].a);
        link(i+n,a[i].b);
        v[i+n]=a[i].d;
      }
      if (find(1,n))
      {
        split(1,n);
        ans=min(ans,data[n]+a[i].c);
      }
    }
    if (ans==1e9) cout<<-1;
    else cout<<ans;
    return 0;
} 

 

posted @ 2018-03-15 23:24  尹吴潇  阅读(135)  评论(0编辑  收藏  举报