您的位置:首页 > 产品设计 > UI/UE

UVALive 4839 HDU 3686 Traffic Real Time Query System

2014-08-30 13:56 465 查看
题意:

寻找图中从一条边到另一条边的路径上必须经过的点的个数

思路:

首先必经过的一定是割点  因此可以先做点双连通然后缩点  缩完点后形成了树  而且树上的路径是满足“非割点-割点-非割点-割点-…”这样的模式的  路径u->v只需要求出他们的lca  则答案可以通过(dis[u]+dis[v]-dis[lca]*2)/2算出

注意:

这题缩点是通过边来进行的  因为这样可以使每条边都在一个连通块中 —— by wuyiqi

PS:

代码中缩点的部分借鉴了 Sd.无心插柳 的代码  感觉很好理解  Orz Sd.无心插柳  Orz wuyiqi

代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long LL;
#define N 20010
#define M 400010
#define inf 2147483647

int n,m,q,tot,idx,top;
int fu[M],fv[M];
int head
,dfn
,low
,belong[M],st[M],Tmp
;
int vis
,dis
,lca
[20];
struct edge
{
int u,v,next;
bool flag;
}ed[M];
pair<int,int> E[M];

void init()
{
tot=idx=top=0;
memset(head,-1,sizeof(head));
memset(dfn,-1,sizeof(dfn));
memset(Tmp,0,sizeof(Tmp));
memset(vis,0,sizeof(vis));
}

void add(int u,int v)
{
ed[tot].u=u;
ed[tot].v=v;
ed[tot].flag=false;
ed[tot].next=head[u];
head[u]=tot++;
}

void tarjan(int u,int fa)
{
int i,j,v;
dfn[u]=low[u]=++idx;
for(i=head[u];~i;i=ed[i].next)
{
v=ed[i].v;
if(ed[i].flag||dfn[v]>=dfn[u]) continue;
ed[i].flag=ed[i^1].flag=true;
st[++top]=i;
if(dfn[v]==-1)
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v])
{
n++;
do
{
j=st[top--];
if(Tmp[ed[j].v]!=n)
{
E[m++]=make_pair(n,ed[j].v);
Tmp[ed[j].v]=n;
}
if(Tmp[ed[j^1].v]!=n)
{
E[m++]=make_pair(n,ed[j^1].v);
Tmp[ed[j^1].v]=n;
}
belong[j>>1]=n;
}while(j!=i);
}
}
else low[u]=min(low[u],dfn[v]);
}
}

void maketable(int u,int from)
{
int i,v;
vis[u]=1;
dis[u]=dis[from]+1;
lca[u][0]=from;
for(i=1;i<20;i++) lca[u][i]=lca[lca[u][i-1]][i-1];
for(i=head[u];~i;i=ed[i].next)
{
v=ed[i].v;
if(v!=from&&!vis[v]) maketable(v,u);
}
}

int findlca(int u,int v)
{
if(dis[v]>dis[u]) swap(u,v);
int i,tmp=dis[u]-dis[v];
for(i=19;tmp;i--)
{
if(tmp>=(1<<i))
{
tmp-=(1<<i);
u=lca[u][i];
}
}
if(u==v) return u;
for(i=19;i>=0;i--)
{
if(lca[u][i]!=lca[v][i])
{
u=lca[u][i];
v=lca[v][i];
}
}
return lca[u][0];
}

int main()
{
int i,j,u,v,f;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m) break;
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
fu[i]=u;
fv[i]=v;
}
m=0;
for(i=1;i<=n;i++)
{
if(dfn[i]==-1) tarjan(i,i);
}
tot=0;
memset(head,-1,sizeof(head));
for(i=0;i<m;i++)
{
add(E[i].first,E[i].second);
add(E[i].second,E[i].first);
}
for(i=1;i<=n;i++)
{
if(!vis[i]) maketable(i,0);
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&i,&j);
u=belong[i-1];
v=belong[j-1];
f=findlca(u,v);
printf("%d\n",(dis[u]+dis[v]-dis[f]*2)/2);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: