Traffic Real Time Query System

  • 无向图的必经点问题
  • 注意栈中n1和y未必相邻,须以y作为终止标记
#include <bits/stdc++.h>
using namespace std;
int to[200005],nx[200005],h[10005],tot,id[10005],tag[10005],e[200005];
int dfn[10005],low[10005];
vector<int>a[20005];
vector<int>dcc[10005];
int cnt,num,root;
bool cut[10005];
stack<int>s;
void add(int u,int v)
{
	tot++;
	to[tot]=v;
	nx[tot]=h[u];
	h[u]=tot;
}
void tarjan(int n1)
{
	dfn[n1]=low[n1]=++tot;
	s.push(n1);
	if(n1==root&&h[n1]==0)
	{
		cnt++;
		dcc[cnt].push_back(n1);
	}
	int tmp=0;
	for(int i=h[n1];i;i=nx[i])
	{
		int y=to[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[n1]=min(low[n1],low[y]);
			if(dfn[n1]<=low[y])
			{
				tmp++;
				if(root!=n1||tmp>=2)
				{
					cut[n1]=true;
				}
				cnt++;
				while(s.top()!=y)
				{
					dcc[cnt].push_back(s.top());
					s.pop();
				}
				dcc[cnt].push_back(y);
				s.pop();
				dcc[cnt].push_back(n1);
			}
		}
		else
		{
			low[n1]=min(low[n1],dfn[y]);
		}
	}
}
int d[20005],f[20005][15],dis[20005];
void dfs(int n1)
{
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=f[n1][0])
		{
			f[a[n1][i]][0]=n1;
			d[a[n1][i]]=d[n1]+1;
			dis[a[n1][i]]=dis[n1]+(n1>cnt);
			dfs(a[n1][i]);
		}
	}
}
void pre()
{
	for(int j=1;j<=14;j++)
	{
		for(int i=1;i<=num;i++)
		{
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
}
int lca(int u,int v)
{
	if(d[u]<d[v])
	{
		swap(u,v);
	}
	for(int i=14;i>=0;i--)
	{
		if(d[v]<=d[f[u][i]])
		{
			u=f[u][i];
		}
	}
	if(u==v)
	{
		return u;
	}
	for(int i=14;i>=0;i--)
	{
		if(f[u][i]!=f[v][i])
		{
			u=f[u][i];
			v=f[v][i];
		}
	}
	return f[u][0];
}
int dist(int u,int v)
{
	int l=lca(u,v);
	return dis[u]+dis[v]-2*dis[l]-(l>cnt);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	while(!(n==0&&m==0))
	{
		tot=1;
		for(int i=1;i<=n;i++)
		{
			h[i]=tag[i]=0;
			dcc[i].clear();
			dfn[i]=0;
			cut[i]=false;
		}
		for(int i=1;i<=m;i++)
		{
			int u,v;
			cin>>u>>v;
			add(u,v);
			add(v,u);
		}
		tot=cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(!dfn[i])
			{
				root=i;
				tarjan(i);
				while(s.size())
				{
					s.pop();
				}
			}
		}
		num=cnt;
		for(int i=1;i<=n;i++)
		{
			if(cut[i])
			{
				num++;
				id[i]=num;
			}
		}
		for(int i=1;i<=num;i++)
		{
			a[i].clear();
			f[i][0]=0;
			d[i]=0;
		}
		for(int i=1;i<=cnt;i++)
		{
			for(int j=0;j<dcc[i].size();j++)
			{
				tag[dcc[i][j]]=i;
			}
			for(int j=0;j<dcc[i].size();j++)
			{
				int x=dcc[i][j];
				for(int k=h[x];k;k=nx[k])
				{
					if(tag[to[k]]==tag[x])
					{
						e[k]=i;
					}
				}
			}
			for(int j=0;j<dcc[i].size();j++)
			{
				if(cut[dcc[i][j]])
				{
					a[i].push_back(id[dcc[i][j]]);
					a[id[dcc[i][j]]].push_back(i);
				}
				else
				{
					id[dcc[i][j]]=i;
				}
			}
		}
		for(int i=1;i<=num;i++)
		{
			if(!d[i])
			{
				d[i]=1;
				dis[i]=0;
				dfs(i);
			}
		}
		pre();
		int q;
		cin>>q;
		for(int i=1;i<=q;i++)
		{
			int u,v;
			cin>>u>>v;
			u=2*u;
			v=2*v;
			cout<<dist(e[u],e[v])<<"\n";
		}
		cin>>n>>m;
	}
	return 0;
}
posted @ 2025-02-05 15:35  D06  阅读(22)  评论(0)    收藏  举报
//雪花飘落效果