您的位置:首页 > 其它

HDU 2874 Connections between cities 离线LCA

2016-05-17 09:18 459 查看
题意:有n个点m条无向边,每一条边都有权值,有q次询问,每次问两点之间的距离。



想法:因为有的城市可能没有连接,所以整个图可能会分成几个块,所以如果是两个不同块的那么肯定是无法互联的,然后其他的点的距离用离线LCA即可。



#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=10000+2;
const int M=1000000+2;
struct node
{
int to,next;
int w;
};
struct node G[N*2];
struct nodeQ
{
int to,next;
int id;
};
struct nodeQ QG[M*2];
int head
,cnt,headQ
,cntQ;
int father
,dis
,vis
;
int ans[M];
void Init(int n)
{
memset(head,-1,sizeof(head));
memset(headQ,-1,sizeof(headQ));
cnt=0;cntQ=0;
for(int i=1;i<=n;i++)
{
father[i]=i;
}
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(ans,-1,sizeof(ans));
}
void add(int a,int b,int c)
{
G[cnt].to=b;
G[cnt].w=c;
G[cnt].next=head[a];
head[a]=cnt++;
}
void addQ(int a,int b,int c)
{
QG[cntQ].to=b;
QG[cntQ].id=c;
QG[cntQ].next=headQ[a];
headQ[a]=cntQ++;
}
int find_set(int x)
{
if(x!=father[x])
father[x]=find_set(father[x]);
return father[x];
}
void union_set(int x,int y)
{
x=find_set(x);
y=find_set(y);
if(x==y) return;
father[y]=x;
}
void lca(int u,int w,int root)
{
vis[u]=root;
dis[u]=w;
for(int i=head[u];i+1;i=G[i].next)
{
int v=G[i].to;
int len=G[i].w;
if(vis[v]) continue;
lca(v,w+len,root);
union_set(u,v);
}
for(int i=headQ[u];i+1;i=QG[i].next)
{
int v=QG[i].to;
if(vis[v]==root)
{
ans[QG[i].id]=dis[u]+dis[v]-2*dis[find_set(v)];
}
}
}
int main()
{
int m,n,q;
while(~scanf("%d%d%d",&n,&m,&q))
{
Init(n);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
for(int i=1;i<=q;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addQ(a,b,i);
addQ(b,a,i);
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
lca(i,0,i);
}
}
for(int i=1;i<=q;i++)
{
if(ans[i]==-1) printf("Not connected\n");
else printf("%d\n",ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: