题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4514

湫湫系列故事——设计风景线

Time Limit: 5000/2000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
#### 问题描述
> 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好。
>   现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度。请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少?
>   其中,可以兴建的路线均是双向的,他们之间的长度均大于0。
#### 输入
> 测试数据有多组,每组测试数据的第一行有两个数字n, m,其含义参见题目描述;
>   接下去m行,每行3个数字u v w,分别代表这条线路的起点,终点和长度。
>
>   [Technical Specification]
>   1. n   2. m   3. 1   4. w 对于每组测试数据,如果能够建成环形(并不需要连接上去全部的风景点),那么输出YES,否则输出最长的长度,每组数据输出一行。
####样例输入
> 3 3
> 1 2 1
> 2 3 1
> 3 1 1
>
####样例输出
> YES
>
## 题意
> o(n)求树的直径

题解

三种方法:

1、两次dfs,随便找个根节点,求出离它最远的点u,然后以u为根求最远的v,那么u,v就是直径。

2、树形dp

求联通块的话,直接上并查集。

3、一次dfs

代码

1、两次dfs、

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=1e5+10; int fa[maxn];
int find(int x){ return fa[x]=fa[x]==x?x:find(fa[x]); } VPII G[maxn]; int n,m; int dep[maxn],vis[maxn];
int Ma; //树直径,两次dfs。
int _v,_Ma;
void dfs(int u,int fa,int d){
vis[u]=1;
dep[u]=d;
if(_Ma<dep[u]){ _Ma=dep[u],_v=u; }
rep(i,0,G[u].sz()){
int v=G[u][i].X,w=G[u][i].Y;
if(v==fa) continue;
dfs(v,u,d+w);
}
} void init(){
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=n;i++) vis[i]=false;
Ma=0;
} int main() {
while(scf("%d%d",&n,&m)==2){
init(); int flag=0;
rep(i,0,m){
int u,v,w;
scf("%d%d%d",&u,&v,&w);
int pu=find(u);
int pv=find(v);
if(pu!=pv){
fa[pv]=pu;
}else{
flag=1;
}
G[u].pb(mkp(v,w));
G[v].pb(mkp(u,w));
} if(flag){
prf("YES\n"); continue;
} for(int i=1;i<=n;i++){
if(!vis[i]){
_v=i,_Ma=0;
dfs(i,-1,0); int u=_v;
_v=u,_Ma=0;
dfs(u,-1,0); Ma=max(Ma,_Ma);
}
} prf("%d\n",Ma); }
return 0;
} /*
5 0
*/

2、树形dp

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=1e5+10; int fa[maxn];
int find(int x){ return fa[x]=fa[x]==x?x:find(fa[x]); } VPII G[maxn]; int n,m; int vis[maxn];
int Ma; ///dp[u][0]存最大深度
///dp[u][1]存次大深度
///ans[u]存有经过u点的最远点对
///id[u]存最大值是从哪个儿子转移上来的。
///第一遍求以u为根的最大深度和次大深度,以及最远顶点对。
///第二遍则求在整个树上的。
int ans[maxn],dp[maxn][2],id[maxn];
void dfs(int u,int fa){
vis[u]=1;
dp[u][0]=dp[u][1]=0;
rep(i,0,G[u].sz()){
int v=G[u][i].X,w=G[u][i].Y;
if(v==fa) continue;
dfs(v,u);
if(dp[u][0]<dp[v][0]+w){
dp[u][1]=dp[u][0];
dp[u][0]=dp[v][0]+w;
id[u]=v;
}else if(dp[u][1]<dp[v][0]+w){
dp[u][1]=dp[v][0]+w;
}
}
ans[u]=dp[u][0]+dp[u][1];
Ma=max(Ma,ans[u]);
} void dfs2(int u,int fa,int w){
if(fa!=-1){
int tmp=(id[fa]==u)?dp[fa][1]:dp[fa][0];
ans[u]=max(ans[u],dp[u][0]+tmp+w);
if(dp[u][0]<=tmp+w){
dp[u][0]=tmp+w;
dp[u][1]=dp[u][0];
id[u]=-1;
}else if(dp[u][1]<tmp+w){
dp[u][1]=tmp+w;
}
}
Ma=max(Ma,ans[u]);
rep(i,0,G[u].sz()){
int v=G[u][i].X;
if(v==fa) continue;
dfs2(v,u,G[u][i].Y);
}
} void init(){
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=n;i++) vis[i]=false;
clr(dp,0); clr(id,-1);
Ma=0;
} int main() {
while(scf("%d%d",&n,&m)==2){
init(); int flag=0;
rep(i,0,m){
int u,v,w;
scf("%d%d%d",&u,&v,&w);
int pu=find(u);
int pv=find(v);
if(pu!=pv){
fa[pv]=pu;
}else{
flag=1;
}
G[u].pb(mkp(v,w));
G[v].pb(mkp(u,w));
} if(flag){
prf("YES\n"); continue;
} for(int i=1;i<=n;i++){
if(!vis[i]){
dfs(i,-1);
dfs2(i,-1,0);
}
} prf("%d\n",Ma); }
return 0;
} /*
5 3
1 2 9
3 4 5
3 5 3
*/

一次dfs:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef int LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=100010; VPII G[maxn];
int fa[maxn];
int find(int x){ return fa[x]=fa[x]==x?x:find(fa[x]); } int n,m; int dp[maxn],ans;
int vis[maxn];
void dfs(int u,int fa){
dp[u]=0;
vis[u]=1;
rep(i,0,G[u].sz()){
int v=G[u][i].X,w=G[u][i].Y;
if(v==fa) continue;
dfs(v,u);
///枚举经过(u,v)边的在以u为根的子树中的最长链
ans=max(ans,dp[v]+w+dp[u]);
dp[u]=max(dp[u],dp[v]+w);
}
} int main() {
while(scf("%d%d",&n,&m)==2){
for(int i=0;i<=n;i++) vis[i]=0;
for(int i=0;i<=n;i++) G[i].clear();
for(int i=0;i<=n;i++) fa[i]=i;
bool flag=false;
rep(i,0,m){
int u,v,w;
scf("%d%d%d",&u,&v,&w);
int pu=find(u),pv=find(v);
if(pu!=pv){
fa[pv]=pu;
}else flag=true;
G[u].pb(mkp(v,w));
G[v].pb(mkp(u,w));
} if(flag){
prf("YES\n");
continue;
} ans=0;
for(int i=1;i<=n;i++){
if(vis[i]) continue;
dfs(i,-1);
} prf("%d\n",ans);
}
return 0;
} //end----------------------------------------------------------------------- /*
6 5
1 2 1
1 3 1
2 6 1
3 4 1
3 5 2
*/

HDU 4514 湫湫系列故事——设计风景线 树的直径的更多相关文章

  1. HDU4514 湫湫系列故事——设计风景线 ——树的直径/树形dp+判环

    中文题面,给出一个图,问能不能成环,如果可以就输出YES.否则输出该树的直径. 这里的判环我们用路径压缩的并查集就能很快的判断出来,可以在输入的同时进行判断.这题重点就是求树的直径. 树直径的性质可以 ...

  2. HDU 4514 湫湫系列故事——设计风景线(并查集+树形DP)

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) To ...

  3. Hdu 4514 湫湫系列故事——设计风景线

    湫湫系列故事--设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total ...

  4. hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  5. HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

  6. hdu 4514 湫湫系列故事――设计风景线(求树的直径)

    随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好.  现在已经勘探确定了n个位置 ...

  7. HDU - 4514 湫湫系列故事——设计风景线(并查集判环)

    题目: 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探确定了n ...

  8. 刷题总结——湫湫系列故事——设计风景线(hdu4514 并差集判环+树的直径)

    题目:   随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好.   现在已经勘探 ...

  9. HDU 4514 湫湫系列故事――设计风景线 (树形DP)

    题意:略. 析:首先先判环,如果有环直接输出,用并查集就好,如果没有环,那么就是一棵树,然后最长的就是树的直径,这个题注意少开内存,容易超内存, 还有用C++交用的少一些,我用G++交的卡在32764 ...

随机推荐

  1. 关于mysql中GROUP_CONCAT函数的使用

    偶然看到公司存储过程中有个字符串拼接的函数,改bug过程中使用到了,还挺有用的,于是记录下来方便记忆,帮助有需要的人. 这是我需要整理的串,他是调用了一个存储过程,传入组织机构的id和迭代层数,返回来 ...

  2. HTTP中常见的各种状态码详解及解决方案

    总结了一些常见的http的状态码,以及常见的解决方案. 一.各范围内状态码大致含义 1xx:临时响应(Informational),需要请求者继续执行操作的状态代码,表示服务器正在接受请求. 2xx: ...

  3. Android ViewPager里的所有图片设置监听打开同一活动显示不同图片

    Android ViewPager里的所有图片设置监听请看前一文章 为了省时所以2层菜单只做一个点击任意图片后显示相应图片的活动 关键点是每个点击对应的图片如何传参给显示的活动 因为只启动一个活动,所 ...

  4. 求Read Depth

    如何划窗统计测序数据的reads数(depth):https://blog.csdn.net/shenshenwu666/article/details/80936374 方法1,用samtools ...

  5. js 中实现aop

    http://fredrik.appelberg.me/2010/05/07/aop-js/ Aop = { // Apply around advice to all matching functi ...

  6. jQuery学习-尺寸坐标

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. 【HNOI2014】道路堵塞

    题面 题解 解法一 这个思路要基于以下一个结论: 当你删掉某条边\((x,x+1)\)时,最短路路线为:\(1\to x(\leq u)\to y(>u) \to n\),并且\(x\to y\ ...

  8. luogu1117 [NOI2016]优秀的拆分

    luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...

  9. Java虚拟机笔记(二):GC垃圾回收和对象的引用

    为什么要了解GC 我们都知道Java开发者在开发过程中是不需要关心对象的回收的,因为Java虚拟机的原因,它会自动回收那些失效的垃圾对象.那我们为什么还要去了解GC和内存分配呢? 答案很简单:当我们需 ...

  10. 菜鸟vimer成长记——第3章、文件

    上一章一直在讲的是vim的文本的操作,本章主要讲的是vim的文件操作. 本章的有些概念和传统的文本编辑器也不尽相同.所以需要注意概念或者切切说是思维习惯的区别. vim 允许在一个编辑会话中编辑多个文 ...