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;
}
寻找图中从一条边到另一条边的路径上必须经过的点的个数
思路:
首先必经过的一定是割点 因此可以先做点双连通然后缩点 缩完点后形成了树 而且树上的路径是满足“非割点-割点-非割点-割点-…”这样的模式的 路径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;
}
相关文章推荐
- UVALive 4839 HDU 3686 Traffic Real Time Query System
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
- Hdu 3686 Traffic Real Time Query System(双联通分量+LCA)
- 【HDU】3686 Traffic Real Time Query System 点双连通+LCA
- HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)
- HDU 3686 Traffic Real Time Query System(点双连通缩点 + LCA)
- 【HDOJ】3686 Traffic Real Time Query System
- 4839 -- Traffic Real Time Query System
- uva 1464 - Traffic Real Time Query System(双联通+LCA)
- HDU Traffic Real Time Query System
- HDU Traffic Real Time Query System
- HDU3686 Traffic Real Time Query System
- HDU3686 Traffic Real Time Query System
- UVALive 4327 Parade(hdu 2490 Parade)
- HDU 2476 | UVALive 4394 - String painter (区间DP)
- 探讨linux进程的三种时间(real time, system cpu time, user cpu time)的实现
- UVALIVE 2675 Peals (POJ 1260 HDU 1300)
- Apparatus, system, and method for automatically minimizing real-time task latency and maximizing non-real time task throughput
- 1)实际时间(real time): 从command命令行开始执行到运行终止的消逝时间; 2)用户CPU时间(user CPU time): 命令执行完成花费的用户CPU时间,即命令在用户态中执行时间总和; 3)系统CPU时间(system CPU time): 命令执行完成花费的系统CPU时
- HDU 3234 | UValive 4487 - Exclusive-OR (加权并查集)