首页 > 代码库 > [HDU2874]Connections between cities
[HDU2874]Connections between cities
题目大意:给你n个节点的森林(注意不是一棵树),m条路径的长度,c个询问,要你回答每个询问两个点i和j的最短距离,或者回答没有连接。
数据范围:2<=n<=10000,0<=m<10000,1<=c<=1000000
解题思路:对于每个节点,求出其到根的距离a[i],然后求两点的最近公共祖先LCA,最后的答案为$a[i]+a[j]-2*a[LCA(i,j)]$。
我用的是Tarjan算法。
注意此题可能出现两个相同点的情况,需要注意一些细节,或者特判。
C++ Code:
#include<cstdio>#include<cstring>using namespace std;int n,m,c,cnt=0,cntq=0,head[10002],headq[1000002],fa[10002],a[10002]={0};bool vis[10002],all[10002];struct edge{ int to,dist,next;}e[20004];struct Q{ int to,next;}q[2000004];int ans[1000002];void addedge(int from,int to,int dist){ cnt++; e[cnt].to=to; e[cnt].dist=dist; e[cnt].next=head[from]; head[from]=cnt; cnt++; e[cnt].to=from; e[cnt].dist=dist; e[cnt].next=head[to]; head[to]=cnt;}int dad(int x){ return(fa[x]==x)?(x):(fa[x]=dad(fa[x]));}void addq(int x,int y){ cntq++; q[cntq].to=y; q[cntq].next=headq[x]; headq[x]=cntq; cntq++; q[cntq].to=x; q[cntq].next=headq[y]; headq[y]=cntq;}void lca(int root,int pre){ fa[root]=root; for(int i=head[root];i;i=e[i].next){ int p=e[i].to; if(p!=pre){ a[p]=a[root]+e[i].dist; lca(p,root); } } vis[root]=all[root]=true; for(int i=headq[root];i;i=q[i].next){ int p=q[i].to; if(vis[p]){ int LCA=dad(p); ans[(i+1)/2]=a[root]+a[p]-a[LCA]*2; } } fa[root]=pre;}int main(){ while(scanf("%d%d%d",&n,&m,&c)!=EOF){ cnt=cntq=0; memset(a,0,sizeof(a)); memset(fa,0,sizeof(fa)); memset(head,0,sizeof(head)); memset(headq,0,sizeof(headq)); memset(e,0,sizeof(e)); memset(q,0,sizeof(q)); memset(ans,-1,sizeof(ans)); memset(all,0,sizeof(all)); for(int i=1;i<=m;i++){ int from,to,dist; scanf("%d%d%d",&from,&to,&dist); addedge(from,to,dist); } for(int i=1;i<=c;i++){ int x,y; scanf("%d%d",&x,&y); addq(x,y); } for(int i=1;i<=n;i++) if(!all[i]){ memset(vis,0,sizeof(vis)); lca(i,0); } for(int i=1;i<=c;i++) if(ans[i]==-1)puts("Not connected");else printf("%d\n",ans[i]); } return 0;}
[HDU2874]Connections between cities
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。