您的位置:首页 > 其它

Hdu 2874 Connections between cities

2015-06-14 19:41 375 查看
题意:

城市 道路 没有环 不一定连通的树 求两城市的最短距离 设想一下就是很多小树 那好办

思路:

lca离线算法 然后有个技巧就是 每次我们tarjan一棵树不是最后树的节点都访问过并且孩子全能找到老爸嘛 那么我们只要做做做做 做到全部的城市都访问过了 就行了 反正你做这颗小树的时候又不会影响到其他树的

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
const int N = 10005;
const int M = 1000005;
int f
,Next[2*N],va[2*N],wi[2*N],Head
;
int vis
;
int nex[2*M],to[2*M],id[M],head
,ans[M];
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
int len,dis
,l;
void add(int u,int v,int w)
{
va[len]=v;
wi[len]=w;
Next[len]=Head[u];
Head[u]=len++;
}
void add_x(int u,int v)
{
to[l]=v;

nex[l]=head[u];
head[u]=l++;
}

void lca(int u,int fa)
{
f[u]=u;
for(int i=Head[u];i!=-1;i=Next[i])
{int v=va[i],w=wi[i];
if(v!=fa){

dis[v]=dis[u]+w;
lca(v,u);
f[v]=u;
}
}
vis[u]=1;
for(int i=head[u];i!=-1;i=nex[i])
{
int v=to[i];
if(vis[v])
{//puts("sadasd");
ans[i/2]=find(v);
}
}

}

int main()
{
int k;
while(~scanf("%d%d%d",&n,&m,&k))
{
len=l=0;
memset(Head,-1,sizeof Head);
memset(head,-1,sizeof head);
for(int i=0;i<m;i++)
{

int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dis[1]=0;
for(int i=0;i<k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
id[i]=u;
add_x(u,v);
add_x(v,u);
}

memset(vis,0,sizeof vis);
memset(f,0,sizeof f);
memset(ans,-1,sizeof ans);
for(int i=1;i<=n;i++)if(vis[i]==0)lca(i,0);
for(int i=0;i<l;i+=2)
{

int a,b,c;
a=to[i];
b=id[i/2];

if(find(a)!=find(b))puts("Not connected");
else  {c=ans[i/2];

printf("%d\n",dis[a]+dis[b]-2*dis[c]);}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: