动态维护一颗最大生成树,注意查询的值不是用来做最大生成树的那个权值。
具体就是把边变成点。一些查找要素都可以放在splay中查找。
还有就是要注意如果有一条边不选的话,那么我们可能不会为它建立结点,所以要特判一下修改的时候它是不是出现了,出现了就不管。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lc ch[now][0]
#define rc ch[now][1]
const int maxn=4e5+105,inf=2e9;
int n,m;
char s[10];
int mp[maxn];
struct Link_Cut_Tree
{
int np,ch[maxn][2],fa[maxn],w[maxn],mi[maxn],sum[maxn],dist[maxn],L[maxn],R[maxn],num[maxn];
bool rev[maxn];
void Initial()
{
np=n;
}
void pushup(int now)
{
mi[now]=w[now];
sum[now]=dist[now];
num[now]=now;
if(lc)
{
sum[now]+=sum[lc];
if(mi[lc]if(rc)
{
sum[now]+=sum[rc];
if(mi[rc]void pushdown(int now)
{
if(rev[now])
{
swap(lc,rc);
rev[lc]^=1;
rev[rc]^=1;
rev[now]=0;
}
}
bool is_rt(int now)
{
return ch[fa[now]][0]!=now && ch[fa[now]][1]!=now;
}
void Link(int i,int d,int j)
{
ch[i][d]=j;
fa[j]=i;
}
void rot(int x)
{
int y=fa[x],z=fa[y];
pushdown(y);pushdown(x);
int d=(ch[y][1]==x);
if(!is_rt(y))Link(z,ch[z][1]==y,x);fa[x]=z;
Link(y,d,ch[x][d^1]);
Link(x,d^1,y);
pushup(y);pushup(x);
}
void Splay(int x)
{
pushdown(x);//果然要加这一句
while(!is_rt(x))
{
int y=fa[x],z=fa[y];
if(!is_rt(y)) rot((ch[y][0]==x)==(ch[z][0]==y)?y:x);
rot(x);
}
}
int acc(int x)
{
int y=0;
while(x)
{
Splay(x);
ch[x][1]=y;
pushup(x);
y=x;
x=fa[x];
}
return y;
}
void mroot(int x)
{
acc(x);Splay(x);rev[x]^=1;
}
int Find(int x)
{
acc(x);
Splay(x);
while(ch[x][0])
{
pushdown(x);
x=ch[x][0];
}
return x;
}
void link(int x,int y)
{
mroot(x);fa[x]=y;
}
void cut(int x,int y)
{
mroot(x);acc(y);Splay(y);
fa[ch[y][0]]=0;ch[y][0]=0;pushup(y);
}
int query(int x,int y)
{
if(Find(x)!=Find(y))return -1;
mroot(x);acc(y);Splay(y);
return sum[y];
}
int mylink(int x,int y,int t,int l)
{
++np;
w[np]=t;
dist[np]=l;
pushup(np);
L[np]=x;R[np]=y;
link(x,np);
link(y,np);
return np;
}
void myCut(int x)
{
cut(x,L[x]);
cut(x,R[x]);
}
void add(int x,int y,int t,int l,int id)//尝试在x,y,w之间连边
{
if(Find(x)!=Find(y))
{
mp[id]=mylink(x,y,t,l);
return;
}
mroot(x);acc(y);Splay(y);
if(mi[y]>=t)return;
myCut(num[y]);
mp[id]=mylink(x,y,t,l);
}
void change(int id,int l)
{
int x=mp[id];
if(!x)return;
Splay(x);
dist[x]=l;
pushup(x);
}
}lct;
//把所有的id都加上n+1
void Init()
{
scanf("%d%d",&n,&m);
lct.Initial();
for(int i=1;i<=n;i++)lct.w[i]=inf,lct.pushup(i);
}
void query()
{
int u,v,id,t,l;
while(m--)
{
scanf("%s",s);
if(s[0]=='f')
{
scanf("%d%d%d%d%d",&id,&u,&v,&t,&l);u++,v++;
lct.add(u,v,t,l,id);
}
else if(s[0]=='m')
{
scanf("%d%d",&u,&v);u++,v++;
printf("%d\n",lct.query(u,v));
}
else
{
scanf("%d%d",&id,&l);
lct.change(id,l);
}
}
}
int main()
{
//freopen("road.in","r",stdin);
//freopen("road.out","w",stdout);
Init();
query();
return 0;
}