求hack:30pts比较新奇的树形dp转移式子
查看原帖
求hack:30pts比较新奇的树形dp转移式子
473401
zcxnb楼主2024/11/29 10:25

转移方程:

附上代码:

#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
using namespace std;
const int N=5e5+5,M=1e6+5,mod=1e9+7;
int n,m,l,colnum,tot;
int dfn[N],low[N],vis[N],s[N],num[N],ednum[N],lg[N+M],dp[N][2][2],cnt[N][2],col[N];
pii edge[M];
vector<pii>b[N];
vector<int>tr[N];
void tarjan(int x,int f){
    dfn[x]=low[x]=++tot;
    vis[x]=1;
    s[++l]=x;
    for(pii i:b[x]){
        int v=i.first;
        if(i.second==f)  continue;
        if(!dfn[v])  tarjan(v,i.second);
        if(vis[v])  low[x]=min(low[x],low[v]);  
    }
    if(dfn[x]<=low[x]){
        colnum++;
        while(s[l]!=x){
            col[s[l]]=colnum;
            num[colnum]++;
            vis[s[l]]=0;
            l--;
        }
        col[s[l]]=colnum;
        num[colnum]++;
        vis[s[l]]=0;
        l--;
    }
}
void dfs(int x,int f){
    bool son=1;
    for(int i:tr[x]){
        if(i==f)  continue;
        son=0;
        dfs(i,x);
        dp[x][0][1]+=dp[i][0][1]*2ll%mod*cnt[x][0]%mod;
        dp[x][1][1]+=dp[i][0][1]*2ll%mod*cnt[x][1]%mod+dp[i][1][1]*cnt[x][0]%mod+dp[i][1][1]%mod*cnt[x][1]%mod;
        dp[x][1][0]+=dp[i][0][1]*2ll%mod*cnt[x][1]%mod+dp[i][1][1]*cnt[x][1]%mod+dp[i][1][0]*2ll%mod*cnt[x][0]%mod;
        dp[x][1][0]%=mod;
        dp[x][0][1]%=mod;
        dp[x][1][1]%=mod;
    }
    if(son){
        dp[x][0][1]=cnt[x][0];
        dp[x][1][1]=dp[x][1][0]=cnt[x][1];
    }
}
signed main(){
    scanf("%lld%lld",&n,&m);
    lg[0]=1;
    for(int i=1;i<=n+m;i++){
        lg[i]=lg[i-1]*2%mod;
    }
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%lld%lld",&u,&v);
        b[u].push_back({v,i});
        b[v].push_back({u,i});
        edge[i]={u,v};
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i])  tarjan(i,0);
    }
    for(int i=1;i<=m;i++){
        int u=edge[i].first,v=edge[i].second;
        if(col[u]==col[v])  ednum[col[u]]++;
        else{
            tr[col[u]].push_back(col[v]);
            tr[col[v]].push_back(col[u]);
        }
    }
    // printf("%d\n",colnum);
    // for(int i=1;i<=colnum;i++){
    //     printf("%d %d\n",num[i],ednum[i]);
    // }
    for(int i=1;i<=colnum;i++){
        cnt[i][0]=lg[ednum[i]];
        cnt[i][1]=((lg[num[i]]-1+mod)%mod*lg[ednum[i]])%mod;
    }
    dfs(1,0);
    printf("%lld",dp[1][1][0]);
    return 0;
}
2024/11/29 10:25
加载中...