luogu3119/bzoj3887 草鉴定 (tarjan缩点+spfa)

首先缩一波点,就变成了一个DAG,边权是出点的大小

那我们走到某个点的时候可能会有两种状态:已经走过反边或者没走过

于是就把一个点拆成两层(x和x+N),第二层的点表示我已经走过反边了,每层中的边和原来一样,但对于边(u,v),我们连一个(v,u+N),表示走了这条边的反边,这条边的边权是u的大小

因为DAG中没有环,所以权值不会被重复计算

然后spfa算从belong[1]到bel[1]+N的最长路就行了

 1 #include<bits/stdc++.h>
 2 #define CLR(a,x) memset(a,x,sizeof(a))
 3 using namespace std;
 4 typedef long long ll;
 5 typedef pair<int,int> pa;
 6 const int maxn=1e5+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 struct Edge{
16     int ne,b,l;
17 }eg[maxn*3];
18 int egh[maxn*2],ect;
19 int eg1[maxn][2],egh1[maxn],ect1;
20 int N,M,dfn[maxn],low[maxn],stk[maxn],sh,tot,bel[maxn],pct,siz[maxn];
21 bool instk[maxn];
22 
23 inline void adeg1(int a,int b){
24     eg1[++ect1][0]=b,eg1[ect1][1]=egh1[a],egh1[a]=ect1;
25 }
26 inline void adeg(int a,int b,int c){
27     eg[++ect].b=b,eg[ect].l=c,eg[ect].ne=egh[a],egh[a]=ect;
28 }
29 
30 void tarjan(int x){
31     dfn[x]=low[x]=++tot,instk[x]=1,stk[++sh]=x;
32     for(int i=egh1[x];i;i=eg1[i][1]){
33         int b=eg1[i][0];
34         if(!dfn[b]) tarjan(b),low[x]=min(low[x],low[b]);
35         else if(instk[b]) low[x]=min(low[x],dfn[b]);
36     }
37     if(dfn[x]==low[x]){
38         ++pct;
39         while(1){
40             instk[stk[sh]]=0;
41             bel[stk[sh]]=pct;siz[pct]++;
42             if(stk[sh--]==x) break;
43         }
44     }
45 }
46 
47 queue<int> q;
48 int dis[maxn*2];
49 bool flag[maxn*2];
50 inline void spfa(){
51     q.push(bel[1]);
52     while(!q.empty()){
53         int p=q.front();q.pop();
54         flag[p]=0;
55         // printf("!%d
",p);
56         for(int i=egh[p];i;i=eg[i].ne){
57             int b=eg[i].b;
58             if(dis[b]<dis[p]+eg[i].l){
59                 dis[b]=dis[p]+eg[i].l;
60                 if(!flag[b]) q.push(b);
61                 flag[b]=1;
62             }
63         }
64     }
65 }
66 
67 int main(){
68     // freopen("testdata.in","r",stdin);
69     int i,j,k;
70     N=rd(),M=rd();
71     for(i=1;i<=M;i++){
72         int a=rd(),b=rd();
73         adeg1(a,b);
74     }
75     for(i=1;i<=N;i++)
76         if(!dfn[i]) tarjan(i);
77     for(i=1;i<=N;i++){
78         int a=bel[i];
79         for(j=egh1[i];j;j=eg1[j][1]){
80             int b=bel[eg1[j][0]];
81             if(a==b) continue;
82             adeg(a,b,siz[b]);
83             adeg(a+N,b+N,siz[b]);
84             adeg(b,a+N,siz[a]);
85         }
86     }
87     spfa();
88     printf("%d
",dis[bel[1]+N]);
89     return 0;
90 }
原文地址:https://www.cnblogs.com/Ressed/p/9934890.html