洛谷 3916 图的遍历
【题解】
先用Tarjan缩环,然后重新建图并在图上跑dfs+DP
// luogu-judger-enable-o2 #include<cstdio> #include<algorithm> #include<cstring> #define rg register #define N 200010 using namespace std; int n,m,tot,top,color,ans[N],last[N],col[N],mx[N],dfn[N],low[N],st[N],r[N][2]; bool vis[N]; struct edge{int to,pre;}e[N]; inline int read(){ int k=0,f=1;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } inline void add(int x,int y){e[++tot]=(edge){y,last[x]}; last[x]=tot;} inline int max(int x,int y){return x>y?x:y;} void tarjan(int x){ dfn[st[++top]=x]=low[x]=++tot; for(rg int i=last[x],to;i;i=e[i].pre) if(!dfn[to=e[i].to]) tarjan(to),low[x]=min(low[x],low[to]); else if(!col[to]) low[x]=min(low[x],dfn[to]); if(dfn[x]==low[x]) for(color++;st[top+1]!=x;top--) col[st[top]]=color,mx[color]=max(mx[color],st[top]); } void dfs(int x){ vis[x]=1; for(rg int i=last[x],to;i;i=e[i].pre){ if(!vis[to=e[i].to]) dfs(to); mx[x]=max(mx[x],mx[to]); } } int main(){ n=read(); m=read(); for(rg int i=1;i<=m;i++) r[i][0]=read(),add(r[i][0],r[i][1]=read()); tot=0; for(rg int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); tot=0; memset(last,0,sizeof(last)); for(rg int i=1;i<=m;i++) if(col[r[i][0]]!=col[r[i][1]]) add(col[r[i][0]],col[r[i][1]]); for(rg int i=1;i<=color;i++) if(!vis[i]) dfs(i); for(rg int i=1;i<=n;i++) printf("%d ",mx[col[i]]); return 0; }