vijos 1476 旅游规划题解

题目链接:https://vijos.org/p/1476

解:因为这一定是一棵树,所以我们多画几次图,就会发现所有的最长路径中心点都一样,且中心点把这条最长路径分成两段等长的路。

那么做法就很简单啦,先求出图的最长路径长度(称为直径),然后找到中心点(如果最长路径长度为偶数的话,就新建一个点,连上中间的两个点,并把原来两点间的路径删去),然后做一次dfs,那些到中心点的距离为半径的,这个点包括它到中心点的路径上的点都是在最长路径上的。

求最长路径有两种方法:

1.随便取一个点为根,先做一次dfs,再找一个深度最大的点为根,再做一次dfs就可以得到最大的深度了(即为最长路径)。

2.这个有点像拓扑排序,我们每次删除都把度为1的点以及相连的边删去,直到剩下点的数目小于等于二,最后最长路径的长度即为删除的次数(删掉一批度为零的点算一次)*2+剩余的点数目。原理其实就是我们每次把最长链的两端删掉,直到没法删为止,那么删除次数*2+剩余点即为答案。

那么看一下具体程序吧。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct ding{
    int to,next;
}edge[500000];
int ch,nex,cnt,maxdep2,maxdep=0,n,dep[300000],dep2[300000],head[300000],root;
bool b[300000];
void dfs(int x,int d)
{
  dep[x]=d;
  if (d>maxdep) {maxdep=d;ch=x;}
  for (int i=head[x];i;i=edge[i].next) if (dep[edge[i].to]==0) dfs(edge[i].to,d+1);
}
int dfs2(int x,int d)
{
  if (d==maxdep/2) return x;
  for (int i=head[x];i;i=edge[i].next)
  if (dep[edge[i].to]<dep[x])  return (dfs2(edge[i].to,d+1));
}
void dfs3(int x)
{
  b[x]=true;
  for (int i=head[x];i;i=edge[i].next)
//保证那个点之前是没被更新的过,且那个点是当前点的父节点
  if ((!b[edge[i].to])&&(dep[edge[i].to]<dep[x]))
dfs3(edge[i].to);
}
void add(int u,int v){edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt;}
int main()
{
  scanf("%d",&n);
  int s,t;
  for (int i=1;i<=n-1;i++)
  {
    scanf("%d%d",&s,&t);
    add(s+1,t+1);add(t+1,s+1);//为了方便处理
  }
  dfs(1,1);
  int ch2=ch; ch=0;
  memset(dep,0,sizeof dep); maxdep=0; dfs(ch2,1);
//用两次dfs得出最长链长度
  int now=dfs2(ch,1);
//从链尾返回,找到中心点的前一个点
//分类讨论
  for (int i=head[now];i;i=edge[i].next) if (dep[edge[i].to]<dep[now]) nex=edge[i].to;
//nex代表当前找到的点后面的点。
//如果路的长度为偶数的话,我们就需要加边,删边,加点,这里我加了一个n +1的点
  if (maxdep%2==0)
{add(nex,n+1);add(n+1,nex);add(n+1,now);add(now,n+1);root=n+1;}
  else root=nex;
//如果长度为奇数,那么中心点就是nex
//删边
  if (maxdep%2==0)
  {
    for (int i=head[now];i;i=edge[i].next)
      if (edge[edge[i].next].to==nex)
      {
        edge[i].next=edge[edge[i].next].next;
        break;
      }
    for (int i=head[nex];i;i=edge[i].next)
      if (edge[edge[i].next].to==now)
      {
        edge[i].next=edge[edge[i].next].next;
        break;
      }
  }
//得到半径,并进行第三次dfs
  int de=maxdep/2+1; maxdep=0; memset(dep,0,sizeof dep); dfs(root,1);
//如果深度等于半径的话,这条路上的点都属于最长路径,我们更新答案
  for (int i=1;i<=n;i++) if (dep[i]==de)  dfs3(i);
  for (int i=1;i<=n;i++) if (b[i]) printf("%d\n",i-1);
  return 0;
} 
时间: 2024-08-03 22:44:25

vijos 1476 旅游规划题解的相关文章

vijos 1476 旅游规划(csapc)

描述 W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包括n个交叉路口和n-1条街道,任意一条街道连接两个交叉路口,并且任意两个交叉路口之间都存在一条路径互相连接.经过长期调查结果显示如果一个交叉路口位于W市交通网的最长路径上,那么这个路口必然拥挤不堪,所谓最长路径定义为某条路径p=(v1,v2,v3-vk),路径经过的路口各不相同且城市中不存在长度>k

Vijos P1476 旅游规划(csapc) 聪哥说我根本不理解树形DP23333333333

我以0为根节点建树,然后做树形dp,first和second就不用说了吧,先两遍dfs找树的直径,在找fir+sec==树的直径(table)的点进行搜索,最后扫一遍所有的点出答案. 虽然慢了点,但能A就行. 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 bool p[200003]; 7 int

07-图6 旅游规划

题目: 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便宜的一条路径. 输入格式: 输入说明:输入数据的第1行给出4个正整数N.M.S.D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N?1):M是高速公路的条数:S是出发地的城市编号:D是目的地的城市编号.随后的M行中,每行给出一条高速公路的信息,分别是:城市1.城市2.高速

PAT 旅游规划

旅游规划 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便宜的一条路径. 考察dijkstra算法   要注意的是  当权重相等时 要更新下费用 AC代码 1 #include <stdio.h> 2 #define MAX 100000 3 typedef struct 4 { 5 int weight; 6 int cost; 7 }gra

PTA 旅游规划(25 分)

7-10 旅游规划(25 分) 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便宜的一条路径. 输入格式: 输入说明:输入数据的第1行给出4个正整数N.M.S.D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N?1):M是高速公路的条数:S是出发地的城市编号:D是目的地的城市编号.随后的M行中,每行给出一条高速公路的信息,分别

一本通1581旅游规划

1581:旅游规划 时间限制: 1000 ms         内存限制: 524288 KB 描述W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包括n个交叉路口和n-1条街道,任意一条街道连接两个交叉路口,并且任意两个交叉路口之间都存在一条路径互相连接.经过长期调查结果显示如果一个交叉路口位于W市交通网的最长路径上,那么这个路口必然拥挤不堪,所谓最长

如何做好农业观光旅游规划和农业休闲旅游开发?

熊大寻旅游规划公司/文 农业旅游是一种新型农业生产经营形式 ,也是一种新型旅游活动项目 ,是在发展农业生产的基础上有机地附加了生态旅游观光功能的交叉性产业 ,是当今旅游新需求的必然产物.农业生态旅游是把农业.生态和旅游业结合起来,利用田园景观.农业生产活动.农村生态环境和农业生态经营模式,吸引游客前来观赏.品尝.作习.体验.健身.科学考察.环保教育.度假.购物的一种新型的旅游开发类型.生态农业旅游是近几年才兴起的一种新型的旅游方式,人们多居住在城市里面,对于农村的概念越来越模糊.所以根据人们返璞

vijos 观光旅游 最小环fl 呆详看

背景 湖南师大附中成为百年名校之后,每年要接待大批的游客前来参观.学校认为大力发展旅游业,可以带来一笔可观的收入. 描述 学校里面有N个景点.两个景点之间可能直接有道路相连,用Dist[I,J]表示它的长度:否则它们之间没有直接的道路相连.这里所说的道路是没有规定方向的,也就是说,如果从I到J有直接的道路,那么从J到I也有,并且长度与之相等.学校规定:每个游客的旅游线路只能是一个回路(好霸道的规定).也就是说,游客可以任取一个景点出发,依次经过若干个景点,最终回到起点.一天,Xiaomengxi

PAT 07-图6 旅游规划 (25分)

有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便宜的一条路径. 输入格式: 输入说明:输入数据的第1行给出4个正整数NN.MM.SS.DD,其中NN(2\le N\le 5002≤N≤500)是城市的个数,顺便假设城市的编号为0~(N-1N−1):MM是高速公路的条数:SS是出发地的城市编号:DD是目的地的城市编号.随后的MM行中,每行给出一条高