HDU 4514 湫湫系列故事——设计风景线 树的直径
题目链接:
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 湫湫系列故事——设计风景线 树的直径的更多相关文章
- HDU4514 湫湫系列故事——设计风景线 ——树的直径/树形dp+判环
中文题面,给出一个图,问能不能成环,如果可以就输出YES.否则输出该树的直径. 这里的判环我们用路径压缩的并查集就能很快的判断出来,可以在输入的同时进行判断.这题重点就是求树的直径. 树直径的性质可以 ...
- HDU 4514 湫湫系列故事——设计风景线(并查集+树形DP)
湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) To ...
- Hdu 4514 湫湫系列故事——设计风景线
湫湫系列故事--设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total ...
- hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)
湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tot ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- hdu 4514 湫湫系列故事――设计风景线(求树的直径)
随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探确定了n个位置 ...
- HDU - 4514 湫湫系列故事——设计风景线(并查集判环)
题目: 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探确定了n ...
- 刷题总结——湫湫系列故事——设计风景线(hdu4514 并差集判环+树的直径)
题目: 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探 ...
- HDU 4514 湫湫系列故事――设计风景线 (树形DP)
题意:略. 析:首先先判环,如果有环直接输出,用并查集就好,如果没有环,那么就是一棵树,然后最长的就是树的直径,这个题注意少开内存,容易超内存, 还有用C++交用的少一些,我用G++交的卡在32764 ...
随机推荐
- ubuntu16.04系统gcc下降和升级
gcc下降 1 安装 sudo apt-get install -y gcc-4.7 sudo apt-get install -y g++-4.7 2 重新建立软连接 cd /usr/bin #进入 ...
- vue父组件为子组件传值传不过去?vue为数组传值,不能直接用等于的方式,要用循环加push的方式
父组件为子组件传值不成功,子组件拿不到值,不能直接赋值,要用循环加push的方式赋值.
- 基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块
基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块 前言 最近学习了 HT for Web flow 插件,除了正常的 flow 效果,其中还有两个十分好用的两个接口 getPercen ...
- [外观] Firemonkey Windows Hint 气球样式
Firemonkey 在 Windows 平台下的 Hint 默认为距形,有些单调,现在只要加入一行代码,就可以有气球箭头样式的 Hint. 修改代码: 请将 FMX.Controls.Win.pas ...
- ACM1001:Sum Problem
Problem Description In this problem, your task is to calculate SUM(n) = 1 + 2 + 3 + ... + n. Input ...
- Ubuntu 16.04 下简单安装使用golang之备忘
刚开始学习Go语言,这里记录下我在Ubuntu 16.04下安装使用golang的过程,方便以后查询. 一.安装 1.添加源 如果使用默认的源安装golang的话,版本太低,只到1.6 ...
- C++引用的用处
原文:http://www.cnblogs.com/ddx-deng/archive/2012/12/16/3755864.html 一.什么是“引用”?声明和使用“引用”要注意哪些问题? 答:引用就 ...
- [Oracle]ORA-01499的处理
如果出现 ORA-01499,说明 table 和 index之间的相互参照出了错: http://iderror.com/errors/oracle/oracle-db/ora-00900-to-o ...
- PostgreSQL的backuplabel file 初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 看代码: /* File path names ...
- 【转载】COM 组件设计与应用(十二)——错误与异常处理
原文:http://vckbase.com/index.php/wv/1238.html 一.前言 程序设计中,错误处理必不可少,而且通常要占用很大的篇幅.本回书着落在 COM 中的错误(异常)的处理 ...