最大编号 tarjan+逆向建图拓扑排序+DAG上DP

Description

给出N 个点,M 条边的有向图,对于每个点v,求A(v) 表示从点v 出发,能到达的编号最大的点。

Input

第1 行,2 个整数N;M。 
接下来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。
 
 
这题实际上很水了
有向图就提示你环肯定先取环里面的最大值
缩环之后逆拓扑排序求出一个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

posted @ 2018-09-29 21:57  saionjisekai  阅读(59)  评论(0编辑  收藏  举报