【洛谷2916】图的遍历

虽然只是普及难度的题,但是思路非常巧妙orz

原题:

 N,M<=1e5

记忆化搜索是不可以的,因为当把一个点的后续状态全部遍历完之前是不能得到这个点的答案的

某个点的后续的某个状态还可能碰到这个点,那么问题来了,这个时候是更新答案还是继续搜索呢?

都不行,更新答案是错误的,因为这个点还没有得到答案,而且继续搜索显然超时了

想不出来,看题解了orz

正确的做法是建反向边,求每个点到达的最大点不好求,就求最大的点能覆盖到的点

这个就很好办了,记忆化搜索即可

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 struct nds{int y,nxt;}e[110000];
 5 int lk[110000],ltp=0;
 6 void ist(int x,int y){
 7     e[++ltp]={y,lk[x]};  lk[x]=ltp;
 8 }
 9 int n,m;
10 int q[110000],hd=0;
11 int f[110000];
12 void bfs(int x){
13     if(f[x])  return ;
14     f[x]=x;
15     q[hd=1]=x;
16     for(int k=1;k<=hd;++k){
17         for(int i=lk[q[k]];i;i=e[i].nxt)
18             if(!f[e[i].y]){
19                 f[e[i].y]=x;
20                 q[++hd]=e[i].y;
21             }
22     }
23 }
24 int main(){
25     cin>>n>>m;
26     int l,r;
27     for(int i=1;i<=m;++i){
28         scanf("%d%d",&l,&r);
29         ist(r,l);
30     }
31     for(int i=n;i>=1;--i){
32         bfs(i);
33     }
34     for(int i=1;i<=n;++i)
35         printf("%d ",f[i]);
36     printf("
");
37     return 0;
38 }
View Code
原文地址:https://www.cnblogs.com/cdcq/p/13341057.html