今晚闲游洛谷,在图论中发现了这独树一帜的记忆化搜索。看到这道题,第一感受就是DFS,每一个点DFS一遍,如果能更新就更新,但是这样的时间复杂度是O(nm),对于1≤N,M≤105的数据显然是承受不住的,会T飞掉~
究其原因,是因为不断地更新,浪费了大量的时间。有没有改进的方法???答案是肯定的。
反向建边
反向建边可以让我们直接从最大的搜,只要最大的能搜到的一定都可以走到最大的,它的答案自然也就是最大的了,之后也就无需进行更新了,然后从最大的往小搜,可以达到下界O(n);
参考程序如下:
#include<iostream> #include<cstring> using namespace std; int maxn[100001],n,m,v[100001],nxt[100001],head[100001],total,b1,b2,x,y; void add() { cin>>b1>>b2; total++; nxt[total]=head[b2]; head[b2]=total; v[total]=b1; } void dfs(int now,int begin) { if(maxn[now])return; maxn[now]=begin; for(int i=head[now];i!=-1;i=nxt[i]) { dfs(v[i],begin); } } int main() { memset(head,-1,sizeof(head)); cin>>n>>m; for(int i=1;i<=m;i++) { add(); } for(int i=n;i>=1;i--) { dfs(i,i); } for(int i=1;i<=n;i++)cout<<maxn[i]<<" "; cout<<endl; }
原文:https://www.cnblogs.com/szmssf/p/10999932.html