1. 程式人生 > >POJ 3694 Tarjan+LCA

POJ 3694 Tarjan+LCA

一個無向圖 求每增加一條邊後 圖的割邊的個數

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;

const int maxn=100007;
vector<int> vt[maxn];
int dfn[maxn],low[maxn];
int vis[maxn],father[maxn];
int sum,cnt;
bool bridge[maxn];

void tarjan(int u)
{
	dfn[u]=low[u]=++cnt;
	vis[u]++;
	int i,v;
	for(i=0;i<vt[u].size();i++)
	{
		v=vt[u][i];
		if(!vis[v])
		{
			father[v]=u;
			tarjan(v);
			low[u]=min(low[v],low[u]);
			if(low[v]>dfn[u])
			{
				sum++;
				bridge[v]=true;
			}
		}
		else if(vis[v]==1&&father[u]!=v)
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	vis[u]++;
}

void deledge(int u)
{
	if(bridge[u])
	{
		bridge[u]=false;
		sum--;
	}
}

void lca(int u,int v)
{
	while(dfn[u]>dfn[v])
	{
		deledge(u);
		u=father[u];
	}
	while(dfn[v]>dfn[u])
	{
		deledge(v);
		v=father[v];
	}
	while(u!=v)
	{
		deledge(u);
		u=father[u];

		deledge(v);
		v=father[v];
	}
}

int main()
{
	int n,m,id=0;
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0&&m==0)
		{
			break;
		}
		if(id)
		{
			puts("");
		}
		int i,j,u,v;
		for(i=1;i<=n;i++)
		{
			vt[i].clear();
		}
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&u,&v);
			vt[u].push_back(v);
			vt[v].push_back(u);
		}
		memset(vis,0,sizeof(vis));
		memset(bridge,0,sizeof(bridge));
		sum=cnt=0;
		for(i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				tarjan(i);
			}
		}

		int q;
		scanf("%d",&q);
		printf("Case %d:\n",++id);
		while(q--)
		{
			scanf("%d%d",&u,&v);
			lca(u,v);
			printf("%d\n",sum);
		}
	}
	return 0;
}