#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits> using namespace std; typedef long long LL; const int MAXN=1e+4 * 3 + 1000; const int MAXM=1e+5 * 2 + 1000; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); struct Edge { int to,next; Edge(){} Edge(int _to,int _next):to(_to),next(_next){} bool operator<(const Edge &x) const { if(to!=x.to)return to<x.to; return next<x.next; } }e[MAXM]; int head[MAXN],tot; int path[MAXN]; int Find(int x){ int tx=x; while(tx!=path[tx])tx=path[tx]; while(x!=path[x]){ int t=path[x]; path[x]=tx; x=t; } return tx; } bool Union(int x,int y){ x=Find(x),y=Find(y); if(x==y)return false; path[x]=y; return true; } multiset <Edge> S,V; multiset <Edge> ::iterator it,it1; void init(){ memset(head,-1,sizeof(head)); tot=0; S.clear();V.clear(); for(int i=1;i<MAXN;i++)path[i]=i; } void AddEdge(int u,int v){ e[tot]=Edge(v,head[u]); head[u]=tot++; e[tot]=Edge(u,head[v]); head[v]=tot++; } int dep[MAXN],son[MAXN],siz[MAXN],fa[MAXN],prew[MAXN]; int tim,id[MAXN],rid[MAXN],top[MAXN]; void dfs1(int u,int father,int w){ fa[u]=father;siz[u]=1;son[u]=-1; prew[u]=w; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(v!=father){ dep[v]=dep[u]+1; dfs1(v,u,1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]])son[u]=v; } } } void dfs2(int u,int tp){ top[u]=tp; id[u]=++tim; rid[tim]=u; if(son[u]==-1)return ; dfs2(son[u],tp); for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(v!=son[u]&&v!=fa[u])dfs2(v,v); } } #define lson L,mid,rt<<1 #define rson mid+1,R,rt<<1|1 struct Tree { int ans,flag; }tr[MAXN<<2]; void pushup(int rt){ tr[rt].ans=tr[rt<<1].ans+tr[rt<<1|1].ans; } void pushdown(int rt){ if(tr[rt].flag){ tr[rt<<1].ans=tr[rt<<1|1].ans=0; tr[rt<<1].flag=tr[rt<<1|1].flag=1; tr[rt].flag=0; } } void build(int L,int R,int rt){ tr[rt].flag=0; if(L==R){ tr[rt].ans=prew[rid[L]]; tr[rt].flag=0; return ; } int mid=(L+R)>>1; build(lson);build(rson); pushup(rt); } void update(int L,int R,int rt,int l,int r){ if(tr[rt].ans==0)return ; if(l<=L&&R<=r){ tr[rt].ans=0; tr[rt].flag=1; return ; } pushdown(rt); int mid=(L+R)>>1; if(l<=mid)update(lson,l,r); if(r>mid)update(rson,l,r); pushup(rt); } int query(int L,int R,int rt,int l,int r){ if(tr[rt].ans==0)return 0; if(l<=L&&R<=r)return tr[rt].ans; pushdown(rt); int mid=(L+R)>>1,ans=0; if(l<=mid)ans+=query(lson,l,r); if(r>mid)ans+=query(rson,l,r); pushup(rt); return ans; } void updatex(int a,int b,int n){ while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]])swap(a,b); update(1,n,1,id[top[a]],id[a]); a=fa[top[a]]; } if(a==b)return ; if(dep[a]>dep[b])swap(a,b); update(1,n,1,id[son[a]],id[b]); } int queryx(int a,int b,int n){ int ans=0; while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]])swap(a,b); ans+=query(1,n,1,id[top[a]],id[a]); a=fa[top[a]]; } if(a==b)return ans; if(dep[a]>dep[b])swap(a,b); ans+=query(1,n,1,id[son[a]],id[b]); return ans; } struct Q { int type,a,b; void init(){ scanf("%d%d%d",&type,&a,&b); } }cs[MAXN*10]; int ans[MAXN*10]; int main() { int T,n,m,q,cas=0; scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&m,&q); init(); for(int i=0,x,y;i<m;i++){ scanf("%d%d",&x,&y); if(x>y)swap(x,y); S.insert(Edge(x,y)); } for(int i=0;i<q;i++){ cs[i].init(); if(cs[i].type==1){ if(cs[i].a>cs[i].b)swap(cs[i].a,cs[i].b); it=S.lower_bound(Edge(cs[i].a,cs[i].b)); S.erase(it); } } for(it=S.begin();it!=S.end();it++){ if(Union(it->to,it->next)){ V.insert(*it); AddEdge(it->to,it->next); } } for(it=V.begin();it!=V.end();it++){ it1=S.lower_bound(*it); S.erase(it1); } dep[1]=0; tim=0; dfs1(1,1,0); dfs2(1,1); build(1,n,1); for(it=S.begin();it!=S.end();it++){ updatex(it->next,it->to,n); } for(int i=q-1;i>=0;i--){ if(cs[i].type==1){ updatex(cs[i].a,cs[i].b,n); } else { ans[i]=queryx(cs[i].a,cs[i].b,n); } } printf("Case #%d:\n",++cas); for(int i=0;i<q;i++) if(cs[i].type==2)printf("%d\n",ans[i]); } return 0; }
|