最大编号 tarjan+逆向建图拓扑排序+DAG上DP
Posted saionjisekai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大编号 tarjan+逆向建图拓扑排序+DAG上DP相关的知识,希望对你有一定的参考价值。
Description
给出N 个点,M 条边的有向图,对于每个点v,求A(v) 表示从点v 出发,能到达的编号最大的点。
Input
第1 行,2 个整数N;M。
接下来M 行,每行2 个整数Ui,Vi,表示边(Ui,Vi)。点用1,2,...,N 编号。
接下来M 行,每行2 个整数Ui,Vi,表示边(Ui,Vi)。点用1,2,...,N 编号。
Output
输出仅一行为N 个整数A(1),A(2),...,A(N)。
Sample Input
4 3
1 2
2 4
4 3
Sample Output
4 4 3 4
Hint
对于60% 的数据,1<=N,K<=10^3;
对于100% 的数据,1<=N,M<=10^5。
对于100% 的数据,1<=N,M<=10^5。
这题实际上很水了
有向图就提示你环肯定先取环里面的最大值
缩环之后逆拓扑排序求出一个DAG序列
在DAG上任意做DP求最大值就好啦!
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #define N 100005 5 using namespace std; 6 struct node{ 7 int u,v; 8 }e[N],e1[N]; 9 int first[N],nxt[N],cnt,n,m; 10 void add(int u,int v){ 11 e[++cnt].u=u; 12 e[cnt].v=v; 13 nxt[cnt]=first[u]; 14 first[u]=cnt; 15 } 16 int first1[N],nxt1[N],cnt1; 17 void add1(int u,int v){ 18 e1[++cnt1].u=u; 19 e1[cnt1].v=v; 20 nxt1[cnt1]=first1[u]; 21 first1[u]=cnt1; 22 } 23 int low[N],dfn[N],instack[N],stack[N],belong[N],maxpo[N],sign,bcc,top1; 24 void tarjan(int x){ 25 low[x]=dfn[x]=++sign; 26 stack[++top1]=x; 27 instack[x]=1; 28 for(int i=first[x];i;i=nxt[i]){ 29 int v=e[i].v; 30 if(!dfn[v]){ 31 tarjan(v); 32 low[x]=min(low[x],low[v]); 33 } 34 else if(instack[v])low[x]=min(low[x],dfn[v]); 35 } 36 if(dfn[x]==low[x]){ 37 bcc++; 38 int t; 39 do{ 40 t=stack[top1--]; 41 belong[t]=bcc; 42 instack[t]=0; 43 maxpo[bcc]=max(maxpo[bcc],t); 44 // cout<<t<<" "; 45 }while(x!=t); 46 } 47 } 48 priority_queue<int>q; 49 int ru[N],top[N],tot; 50 void topsort(){ 51 for(int i=1;i<=bcc;i++){ 52 if(!ru[i]){ 53 q.push(i); 54 } 55 } 56 while(!q.empty()){ 57 int u=q.top(); 58 q.pop(); 59 top[++tot]=u; 60 for(int i=first1[u];i;i=nxt1[i]){ 61 int v=e1[i].v; 62 ru[v]--; 63 if(!ru[v]){ 64 q.push(v); 65 } 66 } 67 } 68 } 69 int a[N],b[N]; 70 int main(){ 71 cin>>n>>m; 72 for(int i=1;i<=m;i++){ 73 cin>>a[i]>>b[i]; 74 add(a[i],b[i]); 75 } 76 for(int i=1;i<=n;i++){ 77 if(!dfn[i])tarjan(i); 78 } 79 for(int i=1;i<=m;i++){ 80 if(belong[a[i]]==belong[b[i]])continue; 81 add1(belong[b[i]],belong[a[i]]);//反向建图才能够确定拓扑序的dp顺序 82 ru[belong[a[i]]]++; 83 // cout<<belong[b[i]]<<" "<<belong[a[i]]<<endl; 84 } 85 topsort(); 86 // for(int i=1;i<=bcc;i++)cout<<top[i]<<" "; 87 for(int i=1;i<=tot;i++){ 88 int u=top[i]; 89 for(int j=first1[u];j;j=nxt1[j]){ 90 int v=e1[j].v; 91 maxpo[v]=max(maxpo[v],maxpo[u]); 92 } 93 } 94 for(int i=1;i<=n;i++){ 95 cout<<maxpo[belong[i]]<<" "; 96 } 97 return 0; 98 }
over
以上是关于最大编号 tarjan+逆向建图拓扑排序+DAG上DP的主要内容,如果未能解决你的问题,请参考以下文章
bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序