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$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...
随机推荐
- YOLOv4没交棒,但YOLOv5来了!
YOLOv4没交棒,但YOLOv5来了! 前言 4月24日,YOLOv4来了! 5月30日,"YOLOv5"来了! 这里的 "YOLOv5" 是带有引号的,因为 ...
- 如何实现一个简易版的 Spring - 如何实现 AOP(终结篇)
前言 在 上篇 实现了 判断一个类的方式是符合配置的 pointcut 表达式.根据一个 Bean 的名称和方法名,获取 Method 对象.实现了 BeforeAdvice.AfterReturni ...
- noip模拟8[星际旅行·砍树·超级树·求和]
也不能算考得好,虽然这次A了一道题,但主要是那道题太简单了,没啥成就感,而且有好多人都A掉了 除了那一道,其他的加起来一共拿了25pts,这我能咋办,无奈的去改题 整场考试的状态并不是很好啊,不知道是 ...
- SpringCloud-OAuth2(二):实战篇
如果不了解Oauth2 是什么.工作流程的可以看我上一篇文章: SpringCloud-OAuth2(一):基础篇 这篇讲的内容是:Oauth2在SpringBoot/SpringCloud中的实战. ...
- 《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)
1.简介 jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有ja ...
- csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」
题目是古埃及神话??? A. 天空龙 傻逼模拟,看来没有滑天下之大稽QAQ,也没有打错快读(大雾...) B. 巨神兵 难度爆增,一脸懵比..... 60分状压: 因为是求有向图,关于有向图好像拓扑用 ...
- WIN10无法进行Android应用开发真机调试解决方案
在WIN10操作系统进行ANDROID开发真机调试时,遇到的问题主要归纳一下有以下几点: 一.没有打开"USB调试"项.这点不再赘述: 二.没有安装ADB Interface驱动: ...
- Java中对象初始化过程
Java为对象初始化提供了多种选项. 当new一个对象的时候,对象初始化开始: 1.首先,JVM加载类(只加载一次,所以,即使多次new对象,下面的代码也只会在第一次new的时候执行一次),此时, 静 ...
- js笔记20
1.DOM零级事件元素绑定多个click,最后只执行最后一个click DOM二级事件绑定多个click,都要执行 注意当绑定的多个事件名,函数名,事件发生阶段三者完全一样时,才执行最后一个 第 ...
- 使用Flex实现图片旋转。
当用flex实现图片旋转的时候,遇到了这样的问题:截图之后,图片还是会继续旋转,应该是canvas这个还有旋转的角度,所以看到效果跟你截图保存下来的效果不一样. 函数: 角度转换为弧度,这里面涉及到了 ...