E94 Tarjan边双缩点+树形DP P8867 [NOIP2022] 建造军营

视频链接: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;
}
复制代码

 

posted @   董晓  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2023-01-06 G48 二项式反演
点击右上角即可分享
微信分享提示