POJ 树的直径和重心
树的直径:(无根)树上最长两点间的最长路径,两次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 树的直径和重心的更多相关文章
- D4 树的直径、重心以及基环树
第一题第二题鉴上我前几篇博客poj1985 poj1849:https://www.cnblogs.com/Tyouchie/p/10384379.html 第三题:数的重心:poj1655 来自sj ...
- poj 1985 Cow Marathon 树的直径
题目链接:http://poj.org/problem?id=1985 After hearing about the epidemic of obesity in the USA, Farmer J ...
- POJ 1985 Cow Marathon && POJ 1849 Two(树的直径)
树的直径:树上的最长简单路径. 求解的方法是bfs或者dfs.先找任意一点,bfs或者dfs找出离他最远的那个点,那么这个点一定是该树直径的一个端点,记录下该端点,继续bfs或者dfs出来离他最远的一 ...
- POJ 2631 Roads in the North(树的直径)
POJ 2631 Roads in the North(树的直径) http://poj.org/problem? id=2631 题意: 有一个树结构, 给你树的全部边(u,v,cost), 表示u ...
- 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花
求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...
- POJ 1985 Cow Marathon(树的直径模板)
http://poj.org/problem?id=1985 题意:给出树,求最远距离. 题意: 树的直径. 树的直径是指树的最长简单路. 求法: 两遍BFS :先任选一个起点BFS找到最长路的终点, ...
- POJ 2631 Roads in the North(求树的直径,两次遍历 or 树DP)
题目链接:http://poj.org/problem?id=2631 Description Building and maintaining roads among communities in ...
- Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序
题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...
- 树形DP 学习笔记(树形DP、树的直径、树的重心)
前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...
随机推荐
- 前端工具 | JS编译器Monaco使用教程
前言 我的需求是可以语法高亮.函数提示功能.自动换行.代码折叠 Monaco Monaco是微软家的,支持的语言很多,还有缩略地图,有时候提示不好用然后包体很大. The Monaco Editor ...
- NVIDIA DGX SUPERPOD 企业解决方案
NVIDIA DGX SUPERPOD 企业解决方案 实现大规模 AI 创新的捷径 NVIDIA DGX SuperPOD 企业解决方案是业界首个支持任何组织大规模实施 AI 的基础架构解决方案.这一 ...
- GPU—加速数据科学工作流程
GPU-加速数据科学工作流程 GPU-ACCELERATE YOUR DATA SCIENCE WORKFLOWS 传统上,数据科学工作流程是缓慢而繁琐的,依赖于cpu来加载.过滤和操作数据,训练和部 ...
- 适用于Linux 2的Windows子系统上的CUDA
适用于Linux 2的Windows子系统上的CUDA Announcing CUDA on Windows Subsystem for Linux 2 为了响应大众的需求,微软在2020年5月的构建 ...
- Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案
近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...
- jmeter链接mysql数据库
一.下载与MySQL对应的jar包 1.1.查询MySQL的版本, 命令语句 :SELECT VERSION(); 1.2.MySQL官网下载jar包 ,https://downloads.mysql ...
- python-selenium 引入包或者类的清晰写法
#cording=gbk#一般最上面放系统自带的包或者类import os import time##第二层放第三方下载的包或者类from selenium import webdriverfrom ...
- 【逆向&编程实战】Metasploit安卓载荷运行流程分析_复现meterpreter模块接管shell
/QQ:3496925334 作者:MG193.7 CNBLOG博客号:ALDYS4 未经许可,禁止转载/ 关于metasploit的安卓模块,前几次的博客我已经写了相应的分析和工具 [Android ...
- 常用的16个Java实用工具类,Java开发人员请收藏!
在Java中,实用程序类是一个定义一组执行常用功能的方法的类.这篇文章展示了最常用的Java实用程序类及其最常用的方法.类列表及其方法列表都按流行度排序.该数据基于GitHub随机选择的50,000个 ...
- NOIP模拟测试5「星际旅行·砍树·超级树」
星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...