三点通信
来源:互联网 发布:上汽集团 知乎 编辑:程序博客网 时间:2024/05/21 17:00
题目描述
输入
输出
样例输入
5 5 3
1 2 20
1 3 20
1 4 20
3 5 15
4 5 15
2 3 4
3 4 5
5 4 4
5 4 3
1 2 20
1 3 20
1 4 20
3 5 15
2 3 4
3 4 5
5 4 4
样例输出
60
30
15
60
55
55
提示
solution
首先考虑一棵树的情况
对于x,y,z三个点
想到先求x,y到LCA(x,y)的距离,再加上LCA(x,y)到z的距离
可是,马上就会发现会有边重复计算。不过好像换y,z或x,z先算就可以了。所以,三种情况都算一下,求个min就可以了。
再来看看n=m的情况,是在一棵树上加了一条边,形成一个环。这是一个基环外向树。
以环上的每一个点为根,形成一些树
考虑三种情况,
1、若x,y,z在同一棵树上,就按照一棵树的情况做
2、若x,y,z有两个点在同一棵树上,另一点在另一棵树上,设x,y在同一棵树上,先求出x,y到LCA(x,y)的距离,再加上LCA(x,y)到root[x]的距离和z到root[z]的距离,最后还有root[x]到root[z]的最短距离(用前缀和处理一下)
3、若x,y,z都不在一棵树上,求出每一个点到根的距离,再加上三个根之间的最短距离
这样子就可以AC了
code:
#include<iostream>#include<cmath>#include<algorithm>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;bool is_bridge[200005];int belong[100005],sum[1000000],vis[100005],id[100005],jh[100005],jhnum,fi,ti,dfn[100005],color[100005],low[100005],n,m,q,Next[200005],head[100005],vet[200005],w[200005],en,fa[100005][20],deep[100005],D[100005];void addedge(int u,int v,long long val){ vet[++en]=v; Next[en]=head[u]; head[u]=en; w[en]=val;}void dfs(int u,int pre){ fa[u][0]=pre; D[u]=D[pre]+1; for(int i=1;i<=16;i++) if(D[u]>=(1<<i)) fa[u][i]=fa[fa[u][i-1]][i-1]; else break; for(int i=head[u];i;i=Next[i]){ int v=vet[i]; if(v!=pre){ deep[v]=deep[u]+w[i]; dfs(v,u); } }}int lca(int x,int y){ if(D[x]<D[y]) swap(x,y); int z=D[x]-D[y]; for(int i=0;i<=16;i++) if(z&(1<<i)) x=fa[x][i]; for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } if(x==y) return x; return fa[x][0];}void tarjan(int u,int pre){ dfn[u]=low[u]=++ti; color[u]=1; for(int i=head[u];i;i=Next[i]){ int v=vet[i]; if(!color[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(v!=pre) low[u]=min(low[u],dfn[v]); if(low[v]>dfn[u]){ is_bridge[i]=true; if(i&1) is_bridge[i+1]=true; else is_bridge[i-1]=true; } }}void Dfs(int u){ jh[++jhnum]=u; id[u]=jhnum; vis[u]=1; for(int i=head[u];i;i=Next[i]) if(!is_bridge[i]&&!vis[vet[i]]) Dfs(vet[i]);}void DFs(int u,int pre){ vis[u]++; for(int i=head[u];i;i=Next[i]) if(!is_bridge[i]&&vis[vet[i]]<2&&vet[i]!=pre){ sum[id[vet[i]]+jhnum*vis[vet[i]]]=sum[id[u]+jhnum*(vis[u]-1)]+w[i]; DFs(vet[i],u); }}void DFS(int u,int pre,int now){ belong[u]=now; fa[u][0]=pre; D[u]=D[pre]+1; for(int i=1;i<=16;i++) if(D[u]>=(1<<i)) fa[u][i]=fa[fa[u][i-1]][i-1]; else break; for(int i=head[u];i;i=Next[i]){ int v=vet[i]; if(v!=pre&&!id[v]){ deep[v]=deep[u]+w[i]; DFS(v,u,now); } }}int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); addedge(y,x,z); } if(m<n){ D[1]=1; dfs(1,0); while(q--){ int x,y,z,ans,xx,yy; scanf("%d%d%d",&x,&y,&z); xx=lca(x,y); yy=lca(xx,z); ans=-deep[yy]*2-deep[xx]+deep[z]+deep[x]+deep[y]; xx=lca(x,z); yy=lca(xx,y); ans=min(ans,-deep[yy]*2-deep[xx]+deep[x]+deep[y]+deep[z]); xx=lca(y,z); yy=lca(x,yy); ans=min(ans,-deep[yy]*2-deep[xx]+deep[x]+deep[y]+deep[z]); printf("%d\n",ans); } } else{ tarjan(1,0); for(int i=1;i<=n;i++) for(int j=head[i];j;j=Next[j]) if(!is_bridge[j]){ fi=i; goto ok; } ok:; memset(vis,0,sizeof(vis)); Dfs(fi); memset(vis,0,sizeof(vis)); DFs(fi,0); for(int i=1;i<=jhnum;i++) DFS(jh[i],0,i); //printf("%d %d %d %d %d\n",sum[1],sum[2],sum[3],sum[4],sum[5]); while(q--){ int x,y,z,ans=1000000000,xx,yy,zz,add; scanf("%d%d%d",&x,&y,&z); //printf("%d %d %d\n",belong[x],belong[y],belong[z]); if(belong[x]==belong[y]&&belong[x]==belong[z]){ xx=lca(x,y); yy=lca(xx,z); ans=min(ans,-deep[yy]*2-deep[xx]+deep[x]+deep[y]+deep[z]); xx=lca(x,z); yy=lca(xx,y); ans=min(ans,-deep[yy]*2-deep[xx]+deep[x]+deep[y]+deep[z]); xx=lca(y,z); yy=lca(x,yy); ans=min(ans,-deep[yy]*2-deep[xx]+deep[x]+deep[y]+deep[z]); } else if(belong[x]==belong[y]){ xx=lca(x,y); ans=deep[x]+deep[y]-deep[xx]+deep[z]; xx=belong[x]; yy=belong[z]; if(xx>yy) swap(xx,yy); ans+=min(sum[yy]-sum[xx],sum[xx+jhnum]-sum[yy]); } else if(belong[x]==belong[z]){ xx=lca(x,z); ans=deep[x]+deep[y]-deep[xx]+deep[z]; xx=belong[x]; yy=belong[y]; if(xx>yy) swap(xx,yy); ans+=min(sum[yy]-sum[xx],sum[xx+jhnum]-sum[yy]); } else if(belong[y]==belong[z]){ xx=lca(z,y); ans=deep[x]+deep[y]-deep[xx]+deep[z]; xx=belong[x]; yy=belong[z]; if(xx>yy) swap(xx,yy); ans+=min(sum[yy]-sum[xx],sum[xx+jhnum]-sum[yy]); } else{ ans=deep[x]+deep[y]+deep[z]; xx=belong[x]; yy=belong[y]; zz=belong[z]; if(xx>yy) swap(xx,yy); if(yy>zz) swap(yy,zz); if(xx>yy) swap(xx,yy); add=sum[zz]-sum[xx]; add=min(add,sum[xx+jhnum]-sum[yy]); add=min(add,sum[yy+jhnum]-sum[zz]); ans+=add; } printf("%d\n",ans); } } return 0;}
阅读全文
0 0
- 三点通信
- 信息与通信教研室在专业建设上的三点做法
- 通信频点
- 点到点通信与端到端通信
- 三种通信方式
- android局域网通信(三)
- 蓝图通信三
- js小记三点
- 三点三十三
- 三点顺序
- 凌晨三点
- NYOJ - 三点顺序
- 三点顺序
- acm-三点顺序
- NYOJ 三点顺序
- 68 三点顺序
- 南阳--三点顺序
- 三点顺序
- linux 中断irq_chip
- numpy中argsort函数用法
- Fresco强大的图片加载组件
- 机器学习损失函数、L1-L2正则化的前世今生
- 【ccf-201503-1】图像旋转
- 三点通信
- 图解HTTP整理(二简单的http协议)
- CSDN无法更新头像
- ThinkPHP5作为后台使用Ajax实现图片上传功能
- ie浏览器提示 "Internet Explorer 已经限制此网页运行脚本或Activex控件"
- mysql 学习相关截图
- 直流电机和交流电机的区别
- C# 获取文件名和扩展名
- 声纹识别技术助力远程身份认证