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\n",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\n",dis[bel[1]+N]); 89 return 0; 90 }