题目链接:

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. InnoDB数据页结构

    前言 ​ 关于数据库我们知道是通过内存对磁盘进行操作的,也知道数据会落实到磁盘上,但是数据在磁盘上的存储结构可能大家还不是很清楚. ​ MySQL服务器上负责对表中的数据的读取和写入的工作的部分是存储 ...

  2. linux-2.6内核驱动学习——jz2440之按键

      //以下是学习完韦东山老师视屏教程后所做学习记录中断方式取得按键值: #include <linux/module.h> #include <linux/kernel.h> ...

  3. C语言中数组定义方式

    <1>前言 大家首先来思考一个问题,若是我们想要定义两个变量,求这两个数的平均数,该怎么求呢? 例如:int a = 10,b = 20 int average = (a + b) / 2 ...

  4. Scala的类继承

    Scala的类继承 extend Scala扩展类的方式和java一样使用extends关键字 class Employee extends Person { } 与java一样,可以在定义的子类重写 ...

  5. PyQt5 笔记(01):嵌套布局

    PyQt5 有四种布局:水平(QHBoxLayout).竖直(QVBoxLayout).网格(QGridLayout).表单(QFormLayout)在窗体中单一的布局应该不难,但若是比较复杂的布局, ...

  6. 11-[CSS]-标准文档流,display,浮动,清除浮动,overflow

    1.标准文档流 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  7. 开发人员常用的DOS命令

    1.远程连接:mstsc /admin 2.开启服务:services.msc 3.打开注册表:regedit 4.IIS服务器重启:iisreset 5.打开记事本:notepad 6.查看系统信息 ...

  8. 用C链表实现约瑟夫环问题

    问题:设有n个人围成一个圆圈,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人再次出列,如此反复,直到所有的人全部出列为止.对于任意给定的n.s.m,求按出列次序 ...

  9. gitlab 配置 ssh key

    打开本地git bash,使用如下命令生成ssh公钥和私钥对 ssh-keygen -t rsa -C 'xxx@xxx.com' 然后一路回车(-C 参数是你的邮箱地址) 然后打开~/.ssh/id ...

  10. ASN.1编码方式详解

    ASN ASN.1 – Abstract Syntax Notation dot one,抽象记法1.数字1被ISO加在ASN的后边,是为了保持ASN的开放性,可以让以后功能更加强大的ASN被命名为A ...