记录编号 461764 评测结果 AAAAAAAAAA
题目名称 [AHOI 2005] LANE 航线规划 最终得分 100
用户昵称 Gravatarwangxh 是否通过 通过
代码语言 C++ 运行时间 0.409 s
提交时间 2017-10-20 17:31:38 内存使用 21.99 MiB
显示代码纯文本
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define pa pair<int,int>
#define mmin(a,b) (a<b?a:b)
struct tree{
	int u,v,next,d;
}l1[301000];
struct tree2{
	int u,v,next;
}l2[201000];
struct tree3{
	int le,ri,d;
}l3[801000];
map<pa,int> ma;
int n,m,lian[201000],e,dfn[30100],low[30100],yan[800100];
int be[30100],cnt,k,num,st[30100],head,cnt2;
int q0[40100],q1[40100],q2[40100],ans[40100];
int fa[30100],size[30100],son[30100],dep[30100],top[30100],dfn2[30100];
bool pd[40100];
void bian(int,int);
void tar(int,int);
void bian2(int,int);
void dfs(int);
void dfs2(int,int);
void build(int,int,int);
void pou1(int,int);
void change(int,int,int);
void pushdown(int);
void pou2(int,int);
int query(int,int,int);
int main()
{
//	freopen("in.txt","r",stdin);
	freopen("lane.in","r",stdin);
	freopen("lane.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		bian(x,y);
		bian(y,x);
	}
	int opt;
	while(1)
	{
		scanf("%d",&opt);
		if(opt==-1) break;
		++k;
		q0[k]=opt;
		scanf("%d%d",&q1[k],&q2[k]);
		if(opt==0) ma[(pa){q1[k],q2[k]}]=1,ma[(pa){q2[k],q1[k]}]=1;
	}
	tar(1,0);
	int cun=e;
	memset(lian,0,sizeof(lian));
	e=0;
	for(int i=1;i<=cun;i++)
	{
		int u=l1[i].u,v=l1[i].v;
		if(ma.count((pa){u,v})==1) continue;
		u=be[u];v=be[v];
		if(u!=v) 
			bian2(u,v);
	}
	dfs(1);
	dfs2(1,1);
	build(1,cnt,1);
	for(int i=k;i>=1;i--)
	{
		if(q0[i]==0) pou1(be[q1[i]],be[q2[i]]);
		else pou2(be[q1[i]],be[q2[i]]);
	}
	for(int i=ans[0];i>=1;i--) printf("%d\n",ans[i]);
	return 0;
}
void bian(int x,int y)
{
	e++;
	l1[e].u=x;
	l1[e].v=y;
	l1[e].next=lian[x];
	lian[x]=e;
}
void tar(int x,int y)
{
	pd[x]=1;
	st[++head]=x;
	dfn[x]=low[x]=++num;
	for(int i=lian[x];i;i=l1[i].next)
	{
		int v=l1[i].v;
		if(v==y) continue;
		if(ma.count((pa){x,v})==1) continue;
		if(dfn[v]==0)
		{
			tar(v,x);
			low[x]=mmin(low[v],low[x]);
		}
		else
			if(pd[v]==1)
				low[x]=mmin(dfn[v],low[x]);
	}
	if(dfn[x]==low[x])
	{
		++cnt;
		int temp;
		while(1)
		{
			temp=st[head];--head;
			pd[temp]=0;
			be[temp]=cnt;
			if(temp==x) break;
		}
	}
}
void bian2(int x,int y)
{
	e++;
	l2[e].u=x;
	l2[e].v=y;
	l2[e].next=lian[x];
	lian[x]=e;
}
void dfs(int x)
{
	size[x]=1;
	for(int i=lian[x];i;i=l2[i].next)
	{
		int v=l2[i].v;
		if(v!=fa[x])
		{
			fa[v]=x;
			dep[v]=dep[x]+1;
			dfs(v);
			size[x]+=size[v];
			if(size[son[x]]>size[v])
				son[x]=v;
		}
	}
}
void dfs2(int x,int y)
{
	dfn2[x]=++cnt2;
	top[x]=y;
	if(son[x]!=0)
		dfs2(son[x],y);
	for(int i=lian[x];i;i=l2[i].next)
	{
		int v=l2[i].v;
		if(fa[x]!=v&&v!=son[x])
			dfs2(v,v);
	}
}
void build(int le,int ri,int i)
{
	l3[i].le=le;
	l3[i].ri=ri;
	if(le==ri)
	{
		l3[i].d=1;
		return;
	}
	int mid=(le+ri)>>1;
	build(le,mid,i*2);
	build(mid+1,ri,i*2+1);
	l3[i].d=l3[i*2].d+l3[i*2+1].d;
}
void pou1(int x,int y)
{
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])
		{
			swap(x,y);
			swap(fx,fy);
		}
		change(dfn2[fx],dfn2[x],1);
		x=fa[fx];
		fx=top[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	if(dep[x]!=dep[y]) change(dfn2[x]+1,dfn2[y],1);
}
void change(int le,int ri,int i)
{
	if(l3[i].le==le&&l3[i].ri==ri)
	{
		l3[i].d=0;
		yan[i]=1;
		return;
	}
	pushdown(i);
	int mid=(l3[i].le+l3[i].ri)>>1;
	if(ri<=mid) change(le,ri,i*2);
	else if(le>mid) change(le,ri,i*2+1);
	else change(le,mid,i*2),change(mid+1,ri,i*2+1);
	l3[i].d=l3[i*2].d+l3[i*2+1].d;
}
void pushdown(int i)
{
	if(yan[i]!=0)
	{
		yan[i*2]=yan[i*2+1]=1;
		yan[i]=0;
		l3[i*2].d=0;
		l3[i*2+1].d=0;
	}
}
void pou2(int x,int y)
{
	int fx=top[x],fy=top[y],sum=0;
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])
		{
			swap(x,y);
			swap(fx,fy);
		}
		sum+=query(dfn2[fx],dfn2[x],1);
		x=fa[fx];
		fx=top[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	if(dep[x]!=dep[y]) sum+=query(dfn2[x]+1,dfn2[y],1);
	ans[++ans[0]]=sum;
}
int query(int le,int ri,int i)
{
	if(l3[i].le==le&&l3[i].ri==ri) return l3[i].d;
	int mid=(l3[i].le+l3[i].ri)>>1;
	if(ri<=mid) return query(le,ri,i*2);
	else if(le>mid) return query(le,ri,i*2+1);
	else return query(le,mid,i*2)+query(mid+1,ri,i*2+1);
}