题目描述:
题解:
仙人掌上$tarjan$。
当然$dfs$树可做但是好像都一样。
考虑用环的顶点表示这个环的贡献,可以依靠$tarjan$进行$dp$。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 50050; const int M = 60050; const int inf = 0x3f3f3f3f; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){c=c*10+ch-‘0‘;ch=getchar();} x = f*c; } int n,m,hed[N],cnt=1; struct EG { int to,nxt; }e[2*M]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int dp[N][2],dep[N],low[N],tim,sta[N],tl; int s[N][2]; int r[N],tr; int sol(int z) { s[1][0] = (z)?-inf:0,s[1][1] = (z)?0:-inf; for(int i=2;i<=tr;i++) { s[i][0] = dp[r[i]][0]+max(s[i-1][0],s[i-1][1]); s[i][1] = dp[r[i]][1]+s[i-1][0]; } return (z)?s[tr][0]:max(s[tr][0],s[tr][1]); } void tarjan(int u,int pre) { dep[u] = low[u] = ++tim; sta[++tl] = u; dp[u][0]=0,dp[u][1]=1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(j==pre)continue; if(!dep[to]) { tarjan(to,j^1); low[u] = min(low[u],low[to]); if(low[to]>dep[u]) { dp[u][0] += max(dp[to][0],dp[to][1]); dp[u][1] += dp[to][0]; tl--; }else if(low[to]==dep[u]) { r[tr=1] = u; while(sta[tl+1]!=to)r[++tr]=sta[tl--]; dp[u][0]+=sol(0); dp[u][1]+=sol(1); } }else low[u] = min(low[u],dep[to]); } } int main() { // freopen("1.in","r",stdin); read(n),read(m); for(int f,t,i=1;i<=m;i++) { read(f),read(t); ae(f,t),ae(t,f); } tarjan(1,0); printf("%d\n",max(dp[1][0],dp[1][1])); return 0; }
原文:https://www.cnblogs.com/LiGuanlin1124/p/10809430.html