树的直径:(无根)树上最长两点间的最长路径,两次dfs即可,第一次dfs任选一点u,找到距离它最远的点s,再从点s进行一次dfs,找到距离s最远的点t,则s-t之间的路径就是树的直径。证明: <http://www.cnblogs.com/wuyiqi/archive/2012/04/08/2437424.html>

poj2631 树的直径裸题

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<iostream>
#include<vector>
typedef long long ll;
using namespace std;
const int maxn=10005;
ll d[maxn];
struct KSD
{
int v,len,next;
}g[maxn];
int vis[maxn];
int head[maxn],cnt;
void add(int u,int v,int len){
g[++cnt].v=v;
g[cnt].next=head[u];
g[cnt].len=len;
head[u]=cnt;
}
void dfs(int x)
{
vis[x]=1;
int i,v;
for(i=head[x];i;i=g[i].next)
{
v=g[i].v;
if(vis[v])continue;
d[v]+=d[x]+g[i].len;
dfs(v);
}
return ;
}
int main(){
int a,b,c;int n=0;
while(scanf("%d%d%d",&a,&b,&c)!=EOF){ n=max(a,max(b,n));
add(a,b,c);
add(b,a,c); }
d[1]=0;
dfs(1);
int m;
ll s=0;
for(int i=1;i<=n;i++){
vis[i]=0;
if(d[i]>s){
m=i;
s=d[i];
}
d[i]=0;
}
dfs(m);
ll ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,d[i]);
printf("%lld\n",ans);
}

poj1985 Cow Marathon 求树的直径裸题

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200005;
int n,m;
struct P{
int v,len,next;
}g[maxn]; int head[maxn],d[maxn],vis[maxn];
int cnt=0;
void add(int u,int v,int len){
g[++cnt].v=v;
g[cnt].next=head[u];
g[cnt].len=len;
head[u]=cnt;
}
void dfs(int x)
{
vis[x]=1;
int i,v;
for(i=head[x];i;i=g[i].next)
{
v=g[i].v;
if(vis[v])continue;
d[v]+=d[x]+g[i].len;
dfs(v);
}
return ;
}
int main(){
scanf("%d%d",&n,&m);
int sum=0;
for(int i=1;i<=n-1;i++){
int x,y,z;
char c;
scanf("%d%d%d %c",&x,&y,&z,&c);
// cout<<c<<endl;
add(x,y,z);
add(y,x,z);
// sum+=z;
}
// sum=sum*2;
d[1]=0;
dfs(1);
int m;
int s=0;
for(int i=1;i<=n;i++){
vis[i]=0;
if(d[i]>s){
m=i;
s=d[i];
}
d[i]=0;
}
dfs(m);
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,d[i]);
// cout<<sum<<" "<<ans<<endl;
printf("%d\n",ans);
}

poj3310 Caterpillar

给你一张无向图,问你这张图是否是一个Caterpillar,Caterpillar必须满足是一个连通图,无环,切存在一条路径,使图中所有的点距离该路径上点的最小距离为1或0

易知改图是一棵树,首先并查集判断是否联通,先找到直径,再判断所有点距离直径距离

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=605;
int fa[maxn],head[maxn],d[maxn],ans[maxn],vis[maxn];
struct P{
int v,len,next;
}g[maxn*2];
int mp[maxn][maxn];
int fi(int x){
if(fa[x]==x)
return x;
return fa[x]=fi(fa[x]);
}
int cnt=0;
void add(int u,int v){
g[++cnt].v=v;
g[cnt].next=head[u];
head[u]=cnt;
}
void dfs(int x)
{
vis[x]=1;
int i,v;
for(i=head[x];i;i=g[i].next)
{
v=g[i].v;
if(vis[v])continue;
d[v]+=d[x]+1;
dfs(v);
}
return ;
}
int n,m,p,q,k=0;
bool DFS(int z){
if(z==q){
ans[z]=1;
return true;
}
vis[z]=1;
for(int i=head[z];i;i=g[i].next){
int v=g[i].v;
if(vis[v])
continue;
if(DFS(v)){
ans[v]=1;
return true;
}
}
return false;
}
int main(){
int cas=0;
while(scanf("%d",&n)&&n!=0){
for(int i=1;i<=n;i++){
d[i]=vis[i]=ans[i]=head[i]=0;
fa[i]=i;
for(int j=1;j<=n;j++)
mp[i][j]=0;
}
scanf("%d",&m);
bool f=1;
if(m!=n-1)
f=0;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=mp[y][x]=1;
x=fi(x);y=fi(y);
if(x==y)
f=0;
fa[x]=y;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
if(fi(i)!=fi(1)){
f=0;
break;
}
if(f==0){
printf("Graph %d is not a caterpillar.\n",++cas);
continue;
}
dfs(1);
int s=0;
for(int i=1;i<=n;i++){
vis[i]=0;
if(d[i]>s){
p=i;
s=d[i];
}
d[i]=0;
} dfs(p);
s=0;
for(int i=1;i<=n;i++){
vis[i]=0;
if(d[i]>s){
q=i;
s=d[i];
}
d[i]=0;
} DFS(p);
for(int i=1;i<=n;i++){
int j=0;
if(ans[i]==0){
for(j=1;j<=n;j++)
if(ans[j]==1){
if(mp[i][j]==1)
break;
}
if(j>n){
f=0;
break;
}
} }
if(f==0){
printf("Graph %d is not a caterpillar.\n",++cas);
}
else printf("Graph %d is a caterpillar.\n",++cas); }
}

poj1849 Two

大雪将城镇的街道覆盖了,两辆铲雪机从同一城市出发,要求将所有街道得雪都铲完,任意一辆铲雪机可以铲任意一条街道,最后两辆车可以停在任意一处,问两辆车的最少运动长度

有些道路可以经过一次,但有些街道需要经过两次,那么即找到一条最长的距离,车子只要走一趟,易知这条路径即为直径,故答案为所有边的长度*2-直径

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200005;
int n,m;
struct P{
int v,len,next;
}g[maxn]; int head[maxn],d[maxn],vis[maxn];
int cnt=0;
void add(int u,int v,int len){
g[++cnt].v=v;
g[cnt].next=head[u];
g[cnt].len=len;
head[u]=cnt;
}
void dfs(int x)
{
vis[x]=1;
int i,v;
for(i=head[x];i;i=g[i].next)
{
v=g[i].v;
if(vis[v])continue;
d[v]+=d[x]+g[i].len;
dfs(v);
}
return ;
}
int main(){
scanf("%d%d",&n,&m);
int sum=0;
for(int i=1;i<=n-1;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
sum+=z;
}
sum=sum*2;
d[1]=0;
dfs(1);
int m;
int s=0;
for(int i=1;i<=n;i++){
vis[i]=0;
if(d[i]>s){
m=i;
s=d[i];
}
d[i]=0;
}
dfs(m);
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,d[i]);
// cout<<sum<<" "<<ans<<endl;
printf("%d\n",sum-ans);
}

poj3099 Go Go Gorelians

给你一张图,已知两两之间的距离为1,问你找出使距离某个点最远距离最小的点,即找到直径,若直径上的点为奇数,则为中间的,若为偶数,则为中间两个,注意输入给的距离是让我们建树的

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std; const int maxn=10005;
int vis[maxn],head[maxn],cnt,v0[maxn];
struct P{
int v,next;
// double len;
}g[maxn];
struct Q{
int i,x,y,z;
}p[maxn];
int d[maxn],ans[maxn];
//int sum=0;
void add(int u,int v){
g[++cnt].v=v;
// g[cnt].len=len;
g[cnt].next=head[u];
head[u]=cnt;
}
int ma; int n; void dfs(int x)
{
vis[x]=1;
int i,v;
for(i=head[x];i;i=g[i].next)
{
v=g[i].v;
if(vis[v])continue;
d[v]+=d[x]+1;
dfs(v);
}
return ;
}
int q;
int l;
bool DFS(int z){
if(z==q){
return true;
}
vis[z]=1;
for(int i=head[z];i;i=g[i].next){
int v=g[i].v;
if(vis[v])
continue;
if(DFS(v)){
ans[++l]=v;
return true;
}
}
return false;
}
int main(){ int c=0;
while(scanf("%d",&n)&&n!=0){
l=0;
ma=1e7;
for(int i=1;i<=1000;i++)
vis[i]=head[i]=ans[i]=d[i]=0;
c=0;
cnt=0;
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&p[i].i,&p[i].x,&p[i].y,&p[i].z);
v0[++c]=p[i].i;
}
for(int i=2;i<=n;i++){
int s=1e9;
int t;
for(int j=1;j<i;j++){
int o=(p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)+(p[i].z-p[j].z)*(p[i].z-p[j].z);
if(o<s){
s=o;
t=p[j].i;
}
}
add(t,p[i].i);
add(p[i].i,t); }
dfs(v0[1]);
int c;
int s=0;
for(int i=1;i<=n;i++){
int k=v0[i];
vis[k]=0;
if(d[k]>s){
c=k;
s=d[k];
}
d[k]=0;
} dfs(c);
s=0;
for(int i=1;i<=n;i++){
int k=v0[i];
vis[k]=0;
if(d[k]>s){
q=k;
s=d[k];
}
d[k]=0;
} DFS(c);
ans[++l]=c;
if(l%2==0){
cout<<min(ans[l/2+1],ans[l/2])<<" "<<max(ans[l/2+1],ans[l/2])<<endl;
}
else printf("%d\n",ans[l/2+1]);
}
}

  

树的重心:如果存在某个节点,其所有子树中最大节点的子树最小,则该节点为树的重心;任选一个点作为根,进行dfs,记录某个节点的子节点数,则满足max(n-son[u]-1,sou[v])取最小的节点u即为树的重心(v为u的子节点);

poj3107 Goldfather

树的重心裸题

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005;
int cnt,d[maxn],vis[maxn],head[maxn],ans[maxn];
struct P{
int v,next;
}g[maxn];
void add(int u,int v){
g[++cnt].v=v;
g[cnt].next=head[u];
head[u]=cnt;
}
int ma=1e9;
int n;
void dfs(int u){
int sum=0;
d[u]=1;
vis[u]=1;
for(int i=head[u];i;i=g[i].next){
int v=g[i].v;
if(vis[v])
continue;
dfs(v);
d[u]+=d[v];
if(d[v]>=ans[u])
ans[u]=d[v];
}
if(n-d[u]>ans[u])
ans[u]=n-d[u];
if(ma>ans[u])
ma=ans[u];
}
int main(){
cnt=0; scanf("%d",&n);
for(int i=1;i<=n;i++){
head[i]=d[i]=vis[i]=0;
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1);
for(int i=1;i<=n;i++){
if(ans[i]==ma)
printf("%d ",i);
}
printf("\n");
}

poj1655 Banlancing Act

求树的重心,输出字典序最小的

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005;
int cnt,d[maxn],vis[maxn],head[maxn];
struct P{
int v,next;
}g[maxn];
void add(int u,int v){
g[++cnt].v=v;
g[cnt].next=head[u];
head[u]=cnt;
}
int ans1,ans2;
int n;
void dfs(int u){
int sum=0;
d[u]=1;
vis[u]=1;
for(int i=head[u];i;i=g[i].next){
int v=g[i].v;
if(vis[v])
continue;
dfs(v);
d[u]+=d[v];
sum=max(sum,d[v]);
}
sum=max(sum,n-d[u]);
if((sum<ans2)||(sum==ans2&&u<ans1)){
ans1=u;
ans2=sum;
} }
int main(){
int t;
scanf("%d",&t);
while(t--){
cnt=0;
ans1=1e8;
ans2=1e8;
scanf("%d",&n);
for(int i=1;i<=n;i++){
head[i]=d[i]=vis[i]=0;
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1);
printf("%d %d\n",ans1,ans2);
}
}

  

POJ 树的直径和重心的更多相关文章

  1. D4 树的直径、重心以及基环树

    第一题第二题鉴上我前几篇博客poj1985 poj1849:https://www.cnblogs.com/Tyouchie/p/10384379.html 第三题:数的重心:poj1655 来自sj ...

  2. poj 1985 Cow Marathon 树的直径

    题目链接:http://poj.org/problem?id=1985 After hearing about the epidemic of obesity in the USA, Farmer J ...

  3. POJ 1985 Cow Marathon && POJ 1849 Two(树的直径)

    树的直径:树上的最长简单路径. 求解的方法是bfs或者dfs.先找任意一点,bfs或者dfs找出离他最远的那个点,那么这个点一定是该树直径的一个端点,记录下该端点,继续bfs或者dfs出来离他最远的一 ...

  4. POJ 2631 Roads in the North(树的直径)

    POJ 2631 Roads in the North(树的直径) http://poj.org/problem? id=2631 题意: 有一个树结构, 给你树的全部边(u,v,cost), 表示u ...

  5. 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花

    求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...

  6. POJ 1985 Cow Marathon(树的直径模板)

    http://poj.org/problem?id=1985 题意:给出树,求最远距离. 题意: 树的直径. 树的直径是指树的最长简单路. 求法: 两遍BFS :先任选一个起点BFS找到最长路的终点, ...

  7. POJ 2631 Roads in the North(求树的直径,两次遍历 or 树DP)

    题目链接:http://poj.org/problem?id=2631 Description Building and maintaining roads among communities in ...

  8. Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序

    题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...

  9. 树形DP 学习笔记(树形DP、树的直径、树的重心)

    前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...

随机推荐

  1. 面部表情视频中进行远程心率测量:ICCV2019论文解析

    面部表情视频中进行远程心率测量:ICCV2019论文解析 Remote Heart Rate Measurement from Highly Compressed Facial Videos: an ...

  2. 图像超分辨率算法:CVPR2020

    图像超分辨率算法:CVPR2020 Unpaired Image Super-Resolution using Pseudo-Supervision 论文地址: http://openaccess.t ...

  3. 对SpringBoot和SpringCloud的理解

    1.SpringCloud是什么 SpringCloud基于SpringBoot提供了一整套微服务的解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于Net ...

  4. win10下abd环境配置

    一.下载安装 Android SDK 下载地址: http://tools.android-studio.org/index.php/sdk 下载完成后进行解压至D盘根目录下,也可以自定义英文路径下 ...

  5. python django框架+vue.js前后端分离

    本文用于学习django+vue.js实现web前后端分离协作开发.以一个添加和删除数据库书籍应用为实例. django框架官方地址:https://www.djangoproject.com/ vu ...

  6. 01:osi七层---基于TCP协议的套接字(socket)

    1 : osi 七层,tcp/ip 五层 1 cs架构和bs架构2 互联网3 osi七层 tcp/ip五层 -物理层   -网线.光纤        -数据链路层       -网卡        - ...

  7. 手把手使用Python语音识别,进行语音转文字

    0. 太长不看系列,直接使用 在1.2官网注册后拿到APISecret和APIKey,直接复制文章2.4demo代码,确定音频为wav格式,采样率为16K,在命令行执行 python single_s ...

  8. 【题解】hdu 3586 Information Disturbing 二分 树形dp

    题目描述 Information DisturbingTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java ...

  9. HTTP请求方法及响应状态码详解

    HTTP请求方法和响应状态详解 HTTP请求方法 HTTP1.0/1.1支持的所有请求方法如下所示: GET 用来请求访问已被URI识别的资源.指定的资源经服务器解析后返回响应内容. POST POS ...

  10. 为你的Go应用创建轻量级Docker镜像?

    缩小Go二进制文件大小 环境 youmen@youmendeMacBook-Pro % gcc -dumpversion 12.0.5 youmen@youmendeMacBook-Pro % go ...