[模板]tarjan缩点+拓扑排序

Posted Slager_Z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板]tarjan缩点+拓扑排序相关的知识,希望对你有一定的参考价值。

题目:给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

   允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

 

题目简述:先tarjan缩点,再从入度为零处进行一次拓扑排序,求最长路即可,话说拓扑排序求最长路真方便。。。

注意: 要明确拓扑的写法,要用栈写最优。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define man 100010
 4 inline int sc()
 5 {    int x=0,f=1;char ch=getchar();
 6     while(!isdigit(ch)){    if(ch==45)f=-1;ch=getchar();}
 7     while(isdigit(ch)) {    x=x*10+ch-48;ch=getchar();}
 8     return x*f;
 9     }
10 /*TEST*/
11 int n,m,c[man],x[man],y[man];
12 /*EDGE*/
13 int head[man<<1],num=0;
14 struct edge
15 {    int next,to,dis;}e[man<<2];
16 inline void add(int from,int to,int dis) 
17 {    e[++num].next=head[from];
18     e[num].to=to;
19     e[num].dis=dis;
20     head[from]=num;
21     }
22 /*TARJAN*/
23 int dfn[man],low[man],bel[man],val[man],cnt=0,dep=0;
24 bool vis[man];
25 int sta[man],top=0;
26 void tarjan(int s)
27 {    low[s]=dfn[s]=++dep;vis[s]=1;sta[++top]=s;
28     for(int i=head[s];i;i=e[i].next)
29     {    int to=e[i].to;
30         if(!dfn[to])
31         {    tarjan(to);
32             low[s]=min(low[s],low[to]);
33             }
34         else if(vis[to])
35         {    low[s]=min(low[s],dfn[to]);}
36         }
37     if(low[s]==dfn[s])
38     {    int j;cnt++;
39         do
40         {    j=sta[top--];
41             vis[j]=0;
42             val[cnt]+=c[j];
43             bel[j]=cnt;
44             }while(j!=s);
45         }
46     }
47 /*TOPSORT*/
48 inline void clear()
49 {    memset(e,0,sizeof(e));
50     memset(head,0,sizeof(head));
51     num=0;
52     }
53 int degree[man],dis[man],maxdis=-10;
54 inline void topsort()
55 {    queue<int >q;
56     for(int i=1;i<=cnt;i++)
57         dis[i]=0;
58     for(int i=1;i<=cnt;i++)
59         if(degree[i]==0) q.push(i),dis[i]=val[i];
60     while(q.size()!=0)
61     {    int u=q.front();q.pop();
62         for(int i=head[u];i;i=e[i].next)
63         {    int to=e[i].to;
64             degree[to]--;
65             if(degree[to]==0) q.push(to);
66             dis[to]=max(dis[to],dis[u]+e[i].dis);
67             }
68         }
69     int ans=0;
70     for(int i=1;i<=cnt;i++)
71         ans=max(ans,dis[i]);
72     printf("%d\n",ans);
73     }
74 int main()
75 {    n=sc();m=sc();
76     for(int i=1;i<=n;i++)
77         c[i]=sc();
78     for(int i=1;i<=m;i++)
79     {    x[i]=sc(),y[i]=sc();
80         add(x[i],y[i],0);
81         }
82     for(int i=1;i<=n;i++)
83         if(!dfn[i]) tarjan(i);
84     clear();
85     for(int i=1;i<=m;i++)
86     {    if(bel[ x[i] ]==bel[ y[i] ]) continue;
87         add(bel[x[i]],bel[y[i]],val[bel[y[i]]]);
88         degree[bel[y[i]]]++;
89         }
90     topsort();
91     return 0;
92     } 

 

以上是关于[模板]tarjan缩点+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

⑦2018=10.7

[ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

HDU 6165 FFF at Valentine(Tarjan缩点+拓扑排序)

BZOJ-1924所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

[POJ 3683] Priest John‘s Busiest Day | 2-SAT +Tarjan缩点跑拓扑排序

bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序