tarjan 算法求强连通分量

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int P=1e6;
 5 const int N=2e6+5;
 6 const int M=2e6+5;
 7 const int inf=0x3f3f3f3f;
 8 struct edge
 9 {
10     int f,t,next;
11     ll v;
12 }e[M];
13 int n,m,tot,all,s,cnt,head[N],dfn[N],low[N],st[N],id[N];
14 int dindex;
15 bool inst[N];
16 ll num[N],sum[100005],val[N];
17 void add(int f,int t,ll v)
18 {
19     e[tot].f=f; e[tot].t=t; e[tot].v=v;
20     e[tot].next=head[f]; head[f]=tot++;
21 }
22 void tarjan(int v)
23 {
24     dindex++;
25     dfn[v]=low[v]=dindex;
26     st[all++]=v; inst[v]=true;
27     for(int i=head[v];~i;i=e[i].next)
28     {
29         int nx=e[i].t;
30         if(!dfn[nx])
31         {
32             tarjan(nx);
33             low[v]=min(low[v],low[nx]);
34         }
35         else if(inst[nx]) low[v]=min(low[v],dfn[nx]);
36     }
37     if(dfn[v]==low[v])
38     {
39         cnt++;
40         while(1)
41         {
42             int cur=st[--all];
43             inst[cur]=false;
44             id[cur]=cnt;
45             if(cur==v) break;
46         }
47     }
48 }
49 ll work(ll x)
50 {
51     ll ans=0;
52     int item=lower_bound(num,num+15001,x)-num;
53     ans-=sum[item];
54     ans+=x*(item+1);
55     ans+=num[item]-x;
56     return ans;
57 }
58 ll dfs(int v)
59 {
60     ll res=0;
61     dfn[v]=1;
62     for(int i=head[v];~i;i=e[i].next)
63     {
64         int nx=e[i].t;
65         if(!dfn[nx]) res=max(res,e[i].v+dfs(nx));
66         else res=max(res,val[nx]+e[i].v);
67     }
68     val[v]+=res;
69     return val[v];
70 }
71 int main()
72 {
73     num[1]=1; cnt=0; all=0; tot=0; dindex=0;
74     for(int i=1;i<=15000;i++) num[i]=num[i-1]+i,sum[i]=sum[i-1]+num[i];
75     memset(head,-1,sizeof(head));
76     scanf("%d%d",&n,&m);
77     for(int i=1;i<=m;i++)
78     {
79         int f,t; ll v;
80         scanf("%d%d%lld",&f,&t,&v);
81         add(f,t,v);
82     }
83     scanf("%d",&s);
84     tarjan(s);
85     int up=tot;
86     for(int i=0;i<up;i++)
87     {
88         int a=e[i].f,b=e[i].t;
89         if(!id[a] || !id[b]) continue;
90         if(id[a]==id[b]) val[id[a]+P]+=work(e[i].v);
91         else if(id[a]<id[b]) add(id[b]+P,id[a]+P,e[i].v);
92         else add(id[a]+P,id[b]+P,e[i].v);
93     }
94     ll ans=dfs(id[s]+P);
95     printf("%lld
",ans);
96     return 0;
97 }
View Code