很好的一道LCT的题目
虽然能马上发现时LCT但是这个性质起码我是画了个图。。。
要处在同一个强联通分量里的点才有两条不重合路径
那么很容易想出来只需要离线每次加边同时缩点就好了
然后只需要打个并查集维护一下当前点被缩成哪个点就好了
我第一次LCT的并查集忘了更新了
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<map>
using namespace std;
char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
struct Node
{
Node *f,*lc,*rc;
Node *Replace;
int Rev;
Node(){Replace=this;}
inline bool H(){return f->lc==this||f->rc==this;}
inline bool l(){return f->lc==this;}
}Place[100001],*empty;
inline void Begin()
{
empty=new Node;
empty->lc=empty->rc=empty->f=empty->Replace=empty;
}
Node*FFF(Node *a){return a->Replace=(a->Replace==a?(a):FFF(a->Replace));}
inline void Rev(Node *a)
{
a->Rev^=1;
Node *l=a->lc;
a->lc=a->rc,a->rc=l;
a->rc->Rev^=1,a->lc->Rev^=1;
}
inline void Lc(Node*a)
{
Node *ne;
if(a->f->H())
if(a->f->l())
a->f->f->lc=a,ne=a->f->f;
else
a->f->f->rc=a,ne=a->f->f;
else if(a->f->f!=a->f) ne=a->f->f;
else ne=a;
a->f->lc=a->rc;
a->rc->f=a->f;
a->rc=a->f;
a->f->f=a;
a->f=ne;
}
inline void Rc(Node*a)
{
Node *ne;
if(a->f->H())
if(a->f->l())
a->f->f->lc=a,ne=a->f->f;
else
a->f->f->rc=a,ne=a->f->f;
else if(a->f->f!=a->f) ne=a->f->f;
else ne=a;
a->f->rc=a->lc;
a->lc->f=a->f;
a->lc=a->f;
a->f->f=a;
a->f=ne;
}
inline void Turn(Node *a)
{a->l()?Lc(a):Rc(a);}
inline void Change(Node*a)
{if(a->f->Rev)Rev(a->f);if(a->Rev)Rev(a);Turn(a);}
inline void TwiChange(Node*a)
{if(a->f->f->Rev)Rev(a->f->f);if(a->f->Rev)Rev(a->f);if(a->Rev)Rev(a);a->l()==a->f->l()?Turn(a->f):Turn(a);Turn(a);}
inline void Splay(Node *a)
{
while(a->H()&&a->f->H())TwiChange(a);
while(a->H())Change(a);
}
inline void Access(Node *a)
{
if(a->Rev)Rev(a);
a->f=FFF(a->f);
while(true)
{
Splay(a);
a->f=FFF(a->f);
if(a->f==a)return;
Splay(a->f);
if(a->f->Rev)Rev(a->f);
a->f->rc=a;
}
}
inline void MakeRoot(Node *a)
{
Access(a);
a->lc->Rev^=1;
a->lc=empty;
}
inline void Split(Node *a,Node *b)
{
MakeRoot(a);
Access(b);
while(a->f!=b)Change(a);
}
void Del(Node*a,Node*Replace)
{
if(a==empty)return;
a->Replace=Replace;
Del(a->lc,Replace);
Del(a->rc,Replace);
}
inline void Ensmall(Node *a,Node *b)
{
Split(a,b);
a->lc->f=b;
b->lc=a->lc;
a->lc=empty;
Del(a,b);
}
struct Query
{
int u,v;
int no;
bool del;
int ans;
inline friend bool operator <(Query a,Query b)
{return a.no>b.no;}
}Q[100001];
struct Side
{
int u,v;
inline void So()
{if(u>v)swap(u,v);}
inline friend bool operator <(Side a,Side b)
{return a.u^b.u?a.u<b.u:a.v<b.v;}
}L[100001];
int F[100001];
int find(int x)
{
return F[x]=(F[x]==x?x:find(F[x]));
}
inline void Link(Node *a,Node *b)
{
MakeRoot(a);
a->f=b;
Access(a);
}
map<Side,bool>D;
int n,m,z;
int main()
{
int i,j,k;
Side tp;
Query t;
Begin();
read(n),read(m),read(z);
for(i=1;i<=n;i++)
Place[i].f=Place+i,Place[i].lc=empty,Place[i].rc=empty,Place[i].Rev=0,F[i]=i,Place[i].Replace=Place+i;
for(i=1;i<=m;i++)
read(tp.u),read(tp.v),tp.So(),D[tp]=true,L[i]=tp;
for(i=1;i<=z;i++)
{
do c=getchar();while(c!='Z'&&c!='P');
if(c=='Z')
{
read(t.u),read(t.v),
t.no=i;t.del=true;
Q[i]=t;
tp.u=t.u,tp.v=t.v;
tp.So();
D[tp]=false;
}
else
{
read(t.u),read(t.v),
t.no=i;t.del=false;
Q[i]=t;
}
}
for(i=1;i<=m;i++)
if(D[L[i]])
{
if(FFF(Place+L[i].u)!=FFF(Place+L[i].v))
if(find(L[i].u)^find(L[i].v))
F[find(L[i].u)]=F[L[i].v],Link(FFF(Place+L[i].u),FFF(Place+L[i].v));
else Ensmall(FFF(Place+L[i].u),FFF(Place+L[i].v));
else;
}
for(i=z;i;i--)
{
if(Q[i].del)
if(FFF(Place+Q[i].u)!=FFF(Place+Q[i].v))
if(find(Q[i].u)^find(Q[i].v))
F[find(Q[i].u)]=F[Q[i].v],Link(FFF(Place+Q[i].u),FFF(Place+Q[i].v));
else Ensmall(FFF(Place+Q[i].u),FFF(Place+Q[i].v));
else;
else
Q[i].ans=FFF(Place+Q[i].u)==FFF(Place+Q[i].v);
}
for(i=1;i<=z;i++)
if(!Q[i].del)puts(Q[i].ans?"TAK":"NIE");
return 0;
}