社区讨论

萌新求调Tarjan缩点树形DP 0pts万紫千红

P8867[NOIP2022] 建造军营参与者 4已保存回复 9

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
9 条
当前快照
1 份
快照标识符
@lo3b9rx7
此快照首次捕获于
2023/10/24 03:49
2 年前
此快照最后确认于
2023/10/24 03:49
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int mod = 1e9+7;
int MM(const int x,const int MOD = mod){return x%MOD;}
const int N = 5e5+5;
const int M = 1e6+5;

int n,m;

struct edge{
    int nxt,to;
} g[M<<1],tree[M<<1];

int head[M<<1],ht[M<<1],ec,ect;

void add(int u,int v){
    g[++ec].nxt=head[u];
    g[ec].to=v;
    head[u]=ec;
}

void addtree(int u,int v){
    tree[++ect].nxt=ht[u];
    tree[ect].to=v;
    ht[u]=ect;
}

int low[N],dfn[N],cnt,vis[N],ccnt,belong[N],csiz[N],s[N],e[N];
stack<int> sta;

void tarjan(int u,int fa){
    dfn[u]=low[u]=(++cnt);
    vis[u]=1;sta.push(u);
    for(int i=head[u];i;i=g[i].nxt){
        int v=g[i].to;
        if(v==fa) continue;
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        ccnt++;
        int v;
        do{
            v=sta.top();sta.pop();
            belong[v]=ccnt;csiz[ccnt]++;
        }while(u!=v);
    }
}

int pow(int a,int b,const int mod){
    if(b==0) return 1;
    if(b==1) return MM(a,mod);
    int ret=pow(a,b>>1,mod);
    ret=MM(ret*ret, mod);
    if(b&1) ret=MM(ret*a,mod);
    return ret;
}

void dfs(int u,int fa){
    s[u]=e[u];
    for(int i=ht[u];i;i=tree[u].nxt){
        int v=tree[u].to;
        if(v==fa) continue;
        dfs(v,u);
        s[u]+=(s[v]+1);
    }
}

int f[N][2],ans;

void dp(int u,int fa){
    for (int i=ht[u],v;i;i=tree[i].nxt) {
        v = tree[i].to;
        if (v==fa) continue;
        dp(v,u);
        f[u][1] =MM(f[u][1] * MM(MM(MM(f[v][0]<<1)+f[v][1]))+MM(f[u][0]*f[v][1]));
        f[u][0] = MM(f[u][0]*MM(MM(f[v][0]<<1)));
    }
    if(u==1) ans=MM(ans+f[u][1]);
    else ans=MM(ans+MM(f[u][1]*pow(2,s[1]-s[u]-1,mod)));
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1,u,v;i<=m;i++){
        cin>>u>>v;
        add(u,v);add(v,u);
    }
    tarjan(1,0);
    for(int i=1;i<=n;i++){
        for(int u=head[i];u;u=g[u].nxt){
            int j=g[u].to;
            if(belong[i]==belong[j]) e[belong[i]]++;
            else addtree(belong[i],belong[j]);
        }
    }
    for(int i=1;i<=ccnt;i++){
        e[i]>>=1;
        f[i][0]=pow(2,e[i],mod);
        f[i][1]=pow(2,csiz[i]+e[i])-f[i][0];
    }
    dfs(1,0);
    dp(1,0);
    cout<<ans;
    return 0;
}

回复

9 条回复,欢迎继续交流。

正在加载回复...