模板:缩点
翻之前记录翻出来缩点的板子
正好今天语文课看tarjan睡着了……
https://www.luogu.org/problemnew/show/P3387
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 using namespace std; 5 const int maxn=10000+10; 6 int n, m, cnt, num, s, top; 7 int v[maxn], dfn[maxn], low[maxn], sd[maxn]; 8 int st[maxn], vis[maxn], d[maxn]; 9 int h[maxn], head[maxn], in[maxn]; 10 struct qwq{ 11 int to, next, from; 12 }edge[maxn*10], ed[maxn*10]; 13 void add(int x,int y){ 14 edge[++cnt].next=head[x]; 15 edge[cnt].from=x; 16 edge[cnt].to=y; 17 head[x]=cnt; 18 } 19 void tarjan(int x){ 20 dfn[x]=low[x]=++num; 21 st[++top]=x; 22 vis[x]=1; 23 for(int i=head[x];i;i=edge[i].next){ 24 int v=edge[i].to; 25 if(!dfn[v]){ 26 tarjan(v); 27 low[x]=min(low[x],low[v]); 28 } 29 else if(vis[v]){ 30 low[x]=min(low[x],dfn[v]); 31 } 32 } 33 if(dfn[x]==low[x]){ 34 int y; 35 while(y=st[top--]){ 36 sd[y]=x; 37 vis[y]=0; 38 if(x==y) break; 39 v[x]+=v[y]; 40 } 41 } 42 } 43 int toposort(){ 44 queue <int> q; 45 int tot=0; 46 for(int i=1; i<=n; i++) 47 if(sd[i]==i && !in[i]){ 48 q.push(i); 49 d[i]=v[i]; 50 } 51 while(!q.empty()){ 52 int k=q.front(); 53 q.pop(); 54 for(int i=h[k]; i; i=ed[i].next){ 55 int a=ed[i].to; 56 d[a]=max(d[a], d[k]+v[a]); 57 in[a]--; 58 if(in[a]==0) q.push(a); 59 } 60 } 61 int ans=0; 62 for(int i=1; i<=n; i++) ans=max(ans,d[i]); 63 return ans; 64 } 65 int main(){ 66 cin>>n>>m; 67 for(int i=1; i<=n; i++){ 68 cin>>v[i]; 69 } 70 for(int i=1; i<=m; i++){ 71 int u, v; 72 cin>>u>>v; 73 add(u, v); 74 } 75 for(int i=1; i<=n; i++){ 76 if(!dfn[i]) tarjan(i); 77 } 78 for(int i=1; i<=m; i++){ 79 int x=sd[edge[i].from],y=sd[edge[i].to]; 80 if(x!=y){ 81 ed[++s].next=h[x]; 82 ed[s].to=y; 83 ed[s].from=x; 84 h[x]=s; 85 in[y]++; 86 } 87 } 88 cout<<toposort()<<endl; 89 return 0; 90 }
"Hello World!"