树的直径:(无根)树上最长两点间的最长路径,两次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. 用TensorRT针对AArch64用户的交叉编译示例

    用TensorRT针对AArch64用户的交叉编译示例 以下介绍如何在x86_64linux下为AArch64 QNX和Linux平台交叉编译TensorRT示例. 2.1. Prerequisite ...

  2. 小白自制Linux开发板 一. 瞎抄原理图与乱画PCB

    因为墨云是基于高中物理水平的电路知识来学习.而且此前也就玩过树莓派.Esp8266之类的开发板,水平基础趋近于零,所以在写这个系列的时候抱着记录的心态.还望不足之处还望大佬们指正. <论语> ...

  3. 实验8、31个最重要的Python Flask面试问题和答案

    实验介绍 1. 实验内容 内容涵盖了31个最热门的Flask面试问题,帮助学生更好的理解Flask. 2. 实验要点 了解面试Flask开发人员的常见问题 实验内容 Flask面试问答 Q:Flask ...

  4. 【NX二次开发】Block UI 指定轴

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  5. 【NX二次开发】Block UI 选择节点

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  6. TCP/IP协议 (图解+秒懂+史上最全)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  7. Java8的Stream API确实很牛,但性能究竟如何?

    Stream Performance 已经对 Stream API 的用法鼓吹够多了,用起简洁直观,但性能到底怎么样呢?会不会有很高的性能损失?本节我们对 Stream API 的性能一探究竟. 为保 ...

  8. sys用户无法远程登陆

    1.用sys用户远程登陆 [oracle@edbjr2p2 admin]$ sqlplus system/oracle@PROD3 as sysdbaSQL*Plus: Release 11.2.0. ...

  9. c#根据名称反射对应的枚举类型

    今天遇到了要配置串口的停止位,这个时候直接反射枚举比较方便. 第一反射所有的枚举值 FieldInfo[] fieldInfoes= typeof(StopBits).GetFields(Bindin ...

  10. ClickHouse学习系列之六【访问权限和账户管理】

    背景 在之前写的文章[用户权限管理]里已经介绍了应该如何设置用户密码以及权限控制.但是只是针对修改配置文件的方式来进行用户权限管理,其实ClickHouse也支持基于RBAC(Role-Based A ...