视频链接:E94 Tarjan边双缩点+树形DP P8867 [NOIP2022] 建造军营_哔哩哔哩_bilibili
P8867 [NOIP2022] 建造军营 - 洛谷 | 计算机科学教育新生态
// Tarjan边双缩点+树形DP O(n) #include<bits/stdc++.h> using namespace std; int read(){ int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } const int N=500010,M=2000010,mod=1e9+7; int n,m; int head[N],ne[M],fr[M],to[M],idx=1; void add(int x,int y){ fr[++idx]=x;to[idx]=y;ne[idx]=head[x];head[x]=idx; } vector<int> e[N]; stack<int> s; int dfn[N],low[N],tim,dcc[N],sum[N],cnt,bri[M],siz[N]; long long f[N][2],pw[M],ans; void tarjan(int x,int ine){ dfn[x]=low[x]=++tim; s.push(x); for(int i=head[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]){ tarjan(y,i); low[x]=min(low[x],low[y]); if(dfn[x]<low[y]) bri[i]=bri[i^1]=1; } else if(i!=(ine^1)) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ ++cnt; while(1){ int y=s.top();s.pop(); dcc[y]=cnt; ++sum[cnt]; if(y==x)break; } } } void dfs(int x,int fa){ siz[x]=1; f[x][0]=1; f[x][1]=pw[sum[x]]-1; for(int y:e[x]){ if(y==fa) continue; dfs(y,x); siz[x]+=siz[y]; f[x][1]=(f[x][1]*f[y][0]*2%mod +f[x][1]*f[y][1]%mod +f[x][0]*f[y][1]%mod)%mod; f[x][0]=f[x][0]*f[y][0]*2%mod; } if(x==1) siz[x]--; ans=(ans+f[x][1]*pw[m-siz[x]])%mod; } int main(){ n=read();m=read(); for(int i=1;i<=m;++i){ //建图 int x=read(),y=read();add(x,y);add(y,x); } tarjan(1,0); //缩点 for(int i=2;i<=idx;++i) //建树 if(bri[i])e[dcc[fr[i]]].push_back(dcc[to[i]]); pw[0]=1; for(int i=1;i<M/2;++i) pw[i]=pw[i-1]*2%mod; dfs(1,0); //DP cout<<ans; }
标签:Tarjan,int,P8867,dfn,E94,双缩点,DP,low From: https://www.cnblogs.com/dx123/p/18651770