今晚闲游洛谷,在图论中发现了这独树一帜的记忆化搜索。看到这道题,第一感受就是DFS,每一个点DFS一遍,如果能更新就更新,但是这样的时间复杂度是O(nm),对于1≤N,M≤105的数据显然是承受不住的,会T飞掉~
究其原因,是因为不断地更新,浪费了大量的时间。有没有改进的方法???答案是肯定的。
反向建边
反向建边可以让我们直接从最大的搜,只要最大的能搜到的一定都可以走到最大的,它的答案自然也就是最大的了,之后也就无需进行更新了,然后从最大的往小搜,可以达到下界O(n);
参考程序如下:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int maxn[100001],n,m,v[100001],nxt[100001],head[100001],total,b1,b2,x,y; 5 void add() 6 { 7 cin>>b1>>b2; 8 total++; 9 nxt[total]=head[b2]; 10 head[b2]=total; 11 v[total]=b1; 12 } 13 void dfs(int now,int begin) 14 { 15 if(maxn[now])return; 16 maxn[now]=begin; 17 for(int i=head[now];i!=-1;i=nxt[i]) 18 { 19 dfs(v[i],begin); 20 } 21 } 22 int main() 23 { 24 memset(head,-1,sizeof(head)); 25 cin>>n>>m; 26 for(int i=1;i<=m;i++) 27 { 28 add(); 29 } 30 for(int i=n;i>=1;i--) 31 { 32 dfs(i,i); 33 } 34 for(int i=1;i<=n;i++)cout<<maxn[i]<<" "; 35 cout<<endl; 36 }