首页 > 其他 > 详细

旅游规划

时间:2018-08-20 13:38:24      阅读:228      评论:0      收藏:0      [点我收藏+]

 

试题描述

    W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员。具体来说,W 市的交通网络十分简单,由 n 个交叉路口和 n−1 条街道构成,交叉路口路口编号依次为 0,1,?,n−1 。任意一条街道连接两个交叉路口,且任意两个交叉路口间都存在一条路径互相连接。

    经过长期调查,结果显示,如果一个交叉路口位于 W 市交通网最长路径上,那么这个路口必定拥挤不堪。所谓最长路径,定义为某条路径 p=(v1,v2,v3,……,vk),路径经过的路口各不相同,且城市中不存在长度大于 k 的路径,因此最长路径可能不唯一。因此 W 市市长想知道哪些路口位于城市交通网的最长路径上。

 

输入
第一行一个整数 n;之后 n−1 行每行两个整数 u,v,表示 u 和 v 的路口间存在着一条街道。
输出
包括若干行,每行包括一个整数——某个位于最长路径上的路口编号。为了确保解唯一,请将所有最长路径上的路口编号按编号顺序由小到大依次输出。
输入示例
10
0 1
0 2
0 4
0 6
0 7
1 3
2 5
4 8
6 9
输出示例
0
1
2
3
4
5
6
8
9
其他说明
数据范围:对于全部数据 1 <= n <= 2×100 000?? 。

 看注释

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
inline int rd()
{
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch==-) f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-0;
    return x*f;
}
inline void write(int x)
{
    if(x<0) putchar(-),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+0);
    return ;
}
int n;
int head[400006],to[400006],nxt[400006];//数组应定要开够!!!!!!!!!! 
int total=0;
void add(int x,int y)
{
    total++;
    to[total]=y;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
int fir[400006],sec[400006];//fir[i]存的是以i为根的最长链,sec[i]是次长链 
int s1[400006],s2[400006];//分别存最长连和次长链是从那个点转移的 
int ans=0;//最长链长度 
int dfs(int x,int la)//x是当前点,la是他的父亲节点 
{
    for(int e=head[x];e;e=nxt[e])
    {
        int h=to[e];
        if(h!=la)
        {
            int d=dfs(h,x)+1;
            if(d>fir[x])
            {
                //注意在给最长链赋值时,要把原来最长链在的额支赋给次长链 
                sec[x]=fir[x];
                s2[x]=s1[x];
                fir[x]=d;
                s1[x]=h;
            }
            else if(d>sec[x])
            {
                sec[x]=d;
                s2[x]=h;
            }
        }
    }
    ans=max(ans,fir[x]+sec[x]);//因为最长链和次长链从不同子树转移,所以书上最长链为两个的和 
    return fir[x];
}
int g[400006];
void dp(int x,int la)
{
    if(x!=0) 
    {
        /*
           玄学存
           因为fir和sec存的是由子树转移的值
           所以就忽略了一种特殊情况
           例子:
                   *
                   |
                   *
                   |
                   *
                  /                  *   *
                /                    *       * 
            所以很明显,我们需要一个数组来存上面的最长链 
        */ 
        if(x!=s1[la]) g[x]=max(fir[la]+1,g[la]+1);//不能从父亲节点直接转移,因为可能是fir,所以用到了s1和s2 
        else g[x]=max(sec[la]+1,g[la]+1);
    }
    for(int e=head[x];e;e=nxt[e]) if(to[e]!=la) dp(to[e],x);
}
int main()
{
    n=rd();
    for(int i=1;i<n;i++)
    {
        int x,y;
        x=rd();
        y=rd();
        add(x,y);//双向存边,因为是无向图 
        add(y,x);
    }
    dfs(0,0);//注意初值,下标从0开始 
    dp(0,0);
    for(int i=0;i<n;i++) if(g[i]+fir[i]==ans||fir[i]+sec[i]==ans) printf("%d\n",i);//输出节点(调了好久QAQ) 
    return 0;
}

最后喜欢的话不如来推荐,评论,关注三连。

不喜欢的话也昧着良心推荐一下吧!!!!

旅游规划

原文:https://www.cnblogs.com/WWHHTT/p/9505050.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!