链接:https://ac.nowcoder.com/acm/contest/547/D
来源:牛客网
题目描述
英仙座流星雨(学名Perseids)是以英仙座γ星附近为辐射点出现的流星雨,也称英仙座γ流星雨。每年在7月20日至8月20日前后出现,于8月13日达到高潮。与象限仪座流星雨、双子座流星雨并称为北半球三大流星雨。
暑假到了,又是一个去看流星雨的好季节。
看流星雨最重要的是什么?当然是许愿。
当一颗流星出现时,可以对其许愿。
你一次可以选择一颗流星进行许愿,每一个愿望都需要一定的时间才能说完,而且中间不能有中断。
但是流星的持续时间通常都很短,很难在流星消失之前把自己的一个愿望说完。
你可以朝着新出现的流星接着许上一个未许完的愿望,当且仅当前一颗流星消失的瞬间另外一颗流星同时出现,
你不可以在一颗流星还在出现的时候转向其他的流星,这样流星之神会生气,厄运会降临
现在给你每颗流星出现和结束的时间,问你许一个愿望的最大时长是多少?
输入描述:
第一行一个数n n<=1000000
表示流星的数目
接下来每行2个数字 x,y (0<=x,y<=1001000 )
表示流星出现的时间和结束的时间
输出描述:
一个数字,表示最长可以连续许愿的时间
示例1
说明
1~4
题意:中文,应该看得懂
思路:将输入的每个流星开始的时间作为起点,进行搜索,找到它所能到达的最远距离(把输入的流星时间段变成一幅单向图),
如果每个都重新搜一遍一定会超时,所以要对搜索过程进行记忆化,将搜索过程的每一结果都用数组存下来,到下次再搜索到时直接取出来用。
代码:
#include<iostream> #include<cstdio> #include<queue> #include<string> #include<string.h> #include<map> #include<vector> #include<cmath> #include<iterator> #define mem(a,b) memset(a,b,sizeof(a) #define MOD 100000007 #define LL long long #define Maxn 1000000 const double pi = acos(-1.0); using namespace std; int n; int tol=0; int head[1001010]; int num[1001010]; //建图 struct edge{ int next; int to; }e[Maxn*3]; void add(int start,int ed){ tol++; e[tol].next=head[start]; e[tol].to=ed; head[start]=tol; } bool vis[1001010]; int t[Maxn]; //搜索 int dfs(int start){ vis[start]=true; int tt=-1; for(int i=head[start];i;i=e[i].next){ if(!vis[e[i].to]){//这个点没有被搜索过,进行搜索 int uy=dfs(e[i].to); //cout<<uy<<" "<<tt<<endl; tt=max(tt,uy); }else{//这个点已经被搜索过了,直接拿出结果来用 tt=max(tt,num[e[i].to]); } } if(tt==-1) return start;//这个点已经没有后继点了,返回这个点,这个即是离start最远的点 else return num[start]=tt;//这个start有一个可更新的最远终点,进行更新 } int main(){ scanf("%d",&n); int start,ed; int u=0; for(int i=0;i<n;i++){ scanf("%d%d",&start,&ed); add(start,ed); t[u++]=start; } int ans=0; for(int i=0;i<u;i++){ if(!vis[t[i]]){//这个点未被计算过,进行搜索计算最远距离 dfs(t[i]); ans=max(ans,num[t[i]]-t[i]);//更新答案 } } cout<<ans<<endl; }