树的直径:(无根)树上最长两点间的最长路径,两次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. 前端工具 | JS编译器Monaco使用教程

    前言 我的需求是可以语法高亮.函数提示功能.自动换行.代码折叠 Monaco Monaco是微软家的,支持的语言很多,还有缩略地图,有时候提示不好用然后包体很大. The Monaco Editor ...

  2. NVIDIA DGX SUPERPOD 企业解决方案

    NVIDIA DGX SUPERPOD 企业解决方案 实现大规模 AI 创新的捷径 NVIDIA DGX SuperPOD 企业解决方案是业界首个支持任何组织大规模实施 AI 的基础架构解决方案.这一 ...

  3. GPU—加速数据科学工作流程

    GPU-加速数据科学工作流程 GPU-ACCELERATE YOUR DATA SCIENCE WORKFLOWS 传统上,数据科学工作流程是缓慢而繁琐的,依赖于cpu来加载.过滤和操作数据,训练和部 ...

  4. 适用于Linux 2的Windows子系统上的CUDA

    适用于Linux 2的Windows子系统上的CUDA Announcing CUDA on Windows Subsystem for Linux 2 为了响应大众的需求,微软在2020年5月的构建 ...

  5. Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案

    近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...

  6. jmeter链接mysql数据库

    一.下载与MySQL对应的jar包 1.1.查询MySQL的版本, 命令语句 :SELECT VERSION(); 1.2.MySQL官网下载jar包 ,https://downloads.mysql ...

  7. python-selenium 引入包或者类的清晰写法

    #cording=gbk#一般最上面放系统自带的包或者类import os import time##第二层放第三方下载的包或者类from selenium import webdriverfrom ...

  8. 【逆向&编程实战】Metasploit安卓载荷运行流程分析_复现meterpreter模块接管shell

    /QQ:3496925334 作者:MG193.7 CNBLOG博客号:ALDYS4 未经许可,禁止转载/ 关于metasploit的安卓模块,前几次的博客我已经写了相应的分析和工具 [Android ...

  9. 常用的16个Java实用工具类,Java开发人员请收藏!

    在Java中,实用程序类是一个定义一组执行常用功能的方法的类.这篇文章展示了最常用的Java实用程序类及其最常用的方法.类列表及其方法列表都按流行度排序.该数据基于GitHub随机选择的50,000个 ...

  10. NOIP模拟测试5「星际旅行·砍树·超级树」

    星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...