ZOJ 3820Building Fire Stations 树的最长链性质(拓展)
来源:互联网 发布:微信好友数据分析软件 编辑:程序博客网 时间:2024/06/07 04:49
题意:
给你一个有n个点的树,n是2个点以上,从中找出两个点作为“消防点”,每个点距离这两个点都有个距离,取短的那个距离叫做“消防距离”,问怎样设置两个点,所有点“消防距离”的最大值最小。
树是有最长链的,最长链上的中点距离其他点的距离最大值是最小的。但是有两个点可以加啊,怎么办?就考虑把树劈开,从最长链的中点处劈开,对于两半各取最长链的中点。对于劈开有歧义的就多找几个点劈几次取最优值。
代码:
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 222222;struct Edge{ int u,v,nxt; Edge(int u=0,int v=0,int nxt=0):u(u),v(v),nxt(nxt){}}edge[maxn<<1];int head[maxn],tot;void init(int n){ tot=0; for(int i=0;i<=n;i++) head[i]=-1;}void add(int u,int v){ edge[tot]=Edge(u,v,head[u]); head[u]=tot++; edge[tot]=Edge(v,u,head[v]); head[v]=tot++;}int q[maxn],vis[maxn],pre[maxn],path[maxn];void clrvis(int n,int u=0){ for(int i=0;i<=n;i++) vis[i] = 0; vis[u]=1;}int bfs(int u){ int tail=0,v,farestv=u; q[tail++]=u; pre[u]=-1; vis[u]=1; for(int i=0;i<tail;i++){ u=q[i]; for(int e=head[u];~e;e=edge[e].nxt){ v=edge[e].v; if(vis[v]) continue; vis[v]=vis[u]+1; pre[v]=u; if(vis[farestv]<vis[v]) farestv=v; q[tail++]=v; } } return farestv;}int getPath(int t){ int n=0; path[++n]=t; while(~pre[t]){ path[++n]=pre[t]; t=pre[t]; } return n;}void getans(int n){ int s,t,pathn,ansdis,ansu,ansv;// Ans centerAns = cutAndGetAns(n,n+1); clrvis(n,n+1); s=bfs(1); clrvis(n,n+1); t=bfs(s); pathn = getPath(t); if(pathn&1){/**odd number points in d*/ /** u-center|v */ int center = path[pathn/2+1],u=path[pathn/2],v=path[pathn/2+2]; clrvis(n,v); s=bfs(u); clrvis(n,v); t=bfs(s); int un = getPath(t); ansu = path[un/2+1]; ansdis = un/2; clrvis(n,center); s=bfs(v); clrvis(n,center); t=bfs(s); int vn = getPath(t); ansv = path[vn/2+1]; ansdis = max(ansdis,vn/2); /** u|center-v */ clrvis(n,u); s=bfs(v); clrvis(n,u); t=bfs(s); un = getPath(t); int ansu2 = path[un/2+1]; int ansdis2 = un/2; clrvis(n,center); s=bfs(u); clrvis(n,center); t=bfs(s); vn = getPath(t); int ansv2 = path[vn/2+1]; ansdis2 = max(ansdis2,vn/2); /** get the optional answer */ if(ansdis>ansdis2){ ansu = ansu2; ansv = ansv2; } }else{/**even number points in d*/ int u=path[pathn/2],v=path[pathn/2+1]; clrvis(n,v); s=bfs(u); clrvis(n,v); t=bfs(s); int un = getPath(t); ansu = path[un/2+1]; ansdis = un/2; clrvis(n,u); s=bfs(v); clrvis(n,u); t=bfs(s); int vn = getPath(t); ansv = path[vn/2+1]; ansdis = max(ansdis,vn/2); } printf("%d %d %d\n",ansdis,ansu,ansv);}int main(){// freopen("data.in","r",stdin); int T,n,u,v; scanf("%d",&T); while(T--){ scanf("%d",&n); init(n); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); } getans(n); } return 0;}
spj!
输入:
4
4
1 2
1 3
1 4
20
1 2
2 3
2 7
3 4
3 14
4 5
4 19
5 6
7 8
7 9
9 10
10 11
10 12
12 13
14 15
15 16
15 17
17 18
19 20
7
1 2
2 3
3 4
4 5
5 6
6 7
5
1 2
2 3
3 4
4 5
输出:
1 1 4
4 14 10
2 2 6
1 2 5
0 0
- ZOJ 3820Building Fire Stations 树的最长链性质(拓展)
- zoj 3820 Building Fire Stations (二分+树的直径)
- zoj 3820 Building Fire Stations (求树的直径)
- ZOJ 3820 Building Fire Stations (二分)
- 【ZOJ】3820 Building Fire Stations 树的直径
- zoj 3820 Building Fire Stations (树的直径)
- ZOJ 3820 Building Fire Stations(树的直径+操作)
- ZOJ 3820 Building Fire Stations(树上的问题)
- 【ZOJ】 3820 Building Fire Stations
- ZOJ 3820 Building Fire Stations
- ZOJ - 3820 Building Fire Stations
- ZOJ 3820 Building Fire Stations
- ZOJ 3820 Building Fire Stations(二分+BFS)
- zoj 3820 Building Fire Stations(二分+bfs)
- zoj 3820 Building Fire Stations(树上乱搞)
- zoj 3820 Building Fire Stations(贪心 + 二分)
- ZOJ 3820 Building Fire Stations 二分+BFS
- ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】
- shell脚本后台运行
- 谈谈新科技媒体
- 如何使用DirectDraw直接显示YUV视频数据
- UIImage的几种应用
- 把sn码转换为二维码
- ZOJ 3820Building Fire Stations 树的最长链性质(拓展)
- OpenCV——非线性滤波器
- SDL 2.0窗口创建的理解
- 第十周项目一——程序填充与阅读(1)
- 第十周项目一(1的拓展)
- HDU44979 GCD and LCM (素因子分解+计数)
- 图像拼接算法及实现
- crontab 定时执行python脚本
- 猿题库高中同步微博运营策划