还是太年轻了,根本没往双连通想…
由于边双连通缩点后是一棵树,那就缩点吧!!
因为边双连通的边不会对答案有贡献!!(定义可知)
#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int maxn=1e5+10;
const int MAXN=1e5+10;
const int MAXM=1e5+10;
int n,m,q,u[maxn],v[maxn];
typedef pair<int,int>p;
vector<int>vec[maxn<<1];
map<p,int>mp;
struct edge{
int u,to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v){
d[++cnt]=(edge){u,v,head[u]},head[u]=cnt;
}
/*缩点部分*/
int vistime;
int dfn[MAXN];
int low[MAXN];
int col[MAXN];
int ccnt;
bool isbridge[MAXM];
void tarjan(int u, int fa)
{
dfn[u] = low[u] = ++vistime;
for (int i = head[u]; i; i = d[i].nxt)
{
int v = d[i].to;
if (!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u])
isbridge[i] = isbridge[i ^ 1] = true;
}
else if (dfn[v] < dfn[u] && v != fa)
{
low[u] = min(low[u], dfn[v]);
}
}
}
void sd(int u)
{
dfn[u] = 1;
col[u] = ccnt;
for (int i = head[u]; i; i = d[i].nxt)
{
int v = d[i].to;
if (isbridge[i])
continue;
if (!dfn[v])
sd(v);
}
}
struct QUERY{
int type,l,r;
}ask[maxn];
int fa[maxn],deep[maxn],siz[maxn],son[maxn];
void dfs1(int u,int father)
{
fa[u]=father, deep[u]=deep[father]+1, siz[u]=1;
for(int i=0;i<vec[u].size();i++)
{
int v=vec[u][i];
if( v==father ) continue;
dfs1(v,u);
siz[u]+=siz[v];
if( siz[son[u]]<siz[v] ) son[u]=v;
}
}
int id[maxn],top[maxn],dfs_num,idf[maxn];
void dfs2(int u,int topf)
{
top[u]=topf,id[u]=++dfs_num,idf[dfs_num]=u;
if( !son[u] ) return;
dfs2( son[u],topf );
for(int i=0;i<vec[u].size();i++ )
{
int v=vec[u][i];
if( v==fa[u]||v==son[u] ) continue;
dfs2(v,v);
}
}
int a[1000009],laz[1000009];
void push_down(int rt,int len )
{
if( laz[rt]==-1 ) return;
laz[rt<<1]=laz[rt], laz[rt<<1|1]=laz[rt];
a[rt<<1]=laz[rt]*( len-len/2 ), a[rt<<1|1]=laz[rt]*( len/2 );
laz[rt]=-1;
}
void build(int rt,int l,int r)
{
laz[rt]=-1,a[rt]=0;
if( l==r ) { a[rt]=1; return; }
build(lson); build(rson);
a[rt] = a[rt<<1] + a[rt<<1|1];
}
void update(int rt,int l,int r,int L,int R,int k)
{
if( l>R||r<L ) return;
if( L<=l&&R>=r )
{
laz[rt]=k,a[rt]=( r-l+1 )*k;
return;
}
push_down( rt,r-l+1 );
update(lson,L,R,k); update(rson,L,R,k);
push_down( rt,r-l+1 );
a[rt]=a[rt<<1]+a[rt<<1+1];
}
void update_lian(int x,int y,int z)
{
while( top[x]!=top[y] )
{
if( deep[top[x]]<deep[top[y]] ) swap(x,y);
update(1,1,ccnt,id[top[x]],id[x],z);
x=fa[top[x]];
}
if( x==y ) return;//相等
if( deep[x]>deep[y] ) swap(x,y);
update(1,1,ccnt,id[son[x]],id[y],z );
}
int query(int rt,int l,int r,int L,int R)
{
if( l>R||r<L ) return 0;
if( L<=l&&R>=r ) return a[rt];
push_down(rt,r-l+1);
return query(lson,L,R)+query(rson,L,R);
}
int query_lian(int x,int y)
{
int res=0;
while( top[x]!=top[y] )
{
if( deep[top[x]]<deep[top[y]] ) swap(x,y);
res+=query(1,1,ccnt,id[top[x]],id[x] );
x=fa[top[x]];
}
if( deep[x]>deep[y] ) swap(x,y);
if( x!=y )
res+=query(1,1,ccnt,id[son[x]],id[y] );
return res;
}
int main()
{
int casenum=0,T;
cin >> T;
while( T-- )
{
cnt=1,ccnt=0;
memset(id,0,sizeof(id));
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(isbridge,0,sizeof(isbridge));
memset(col,0,sizeof(col));
memset(son,-1,sizeof(son));
memset(siz,0,sizeof(siz));
vistime=0;dfs_num=0;
for(int i=0;i<=200000;i++) vec[i].clear();
mp.clear();
cin >> n >> m >> q;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u[i],&v[i]);
if( u[i]>v[i] ) swap(u[i],v[i]);
mp[p(u[i],v[i])]++;
}
for(int i=1;i<=q;i++)
{
scanf("%d%d%d",&ask[i].type,&ask[i].l,&ask[i].r);
if( ask[i].l>ask[i].r ) swap( ask[i].l,ask[i].r );
if( ask[i].type==2 ) continue;
mp[ p(ask[i].l,ask[i].r)]--;
}
for(int i=1;i<=m;i++)
{
p w=(p){ u[i],v[i] };
if( mp[w]==0 ) continue;
add(u[i],v[i]); add(v[i],u[i]);
mp[w]--;
}
for(int i=1;i<=n;i++)
if( !dfn[i] ) tarjan(i,-1);
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=n;i++)
if( !dfn[i] )
ccnt++,sd(i);
for(int i=2;i<=cnt;i++)
{
int u=d[i].u,v=d[i].to;
if( col[u]!=col[v] )
vec[ col[u] ].push_back( col[v] );
}
dfs1(1,0);
dfs2(1,1);
build(1,1,ccnt);
vector<int>ans;
for(int i=q;i>=1;i--)
{
int type=ask[i].type,l=ask[i].l,r=ask[i].r;
if( type==1 )
update_lian( id[l],id[r],0 );
else
ans.push_back( query_lian(id[l],id[r] ) );
}
printf("Case #%d:\n", ++casenum);
for(int i=ans.size()-1;i>=0;i--)
printf("%d\n",ans[i]);
}
}