55 pts tarjan缩点后树形dp 求调, 玄关
查看原帖
55 pts tarjan缩点后树形dp 求调, 玄关
617130
Yorg楼主2024/11/22 14:53

代码

#include <bits/stdc++.h>
#define int long long
const int MAXM = 2e6 + 20;
const int MAXN = 5e5 + 20;
const int MOD = 1e9 + 7;

int n, m;
int Pow[2000000 + 20];

int Ans = 0;
int SumeDCC[MAXN]; // eDCC 和, 隶属于 Graph1
int f[MAXN][2];
int Col[MAXN]; // eDCC 编号, 隶属于 Graph2
int SumTree[MAXN]; // 子树和, 隶属于 Graph2
int low[MAXN], dfn = 0;
class Graph_Class
{
private:

public:
    void dfs1(int Now, int fa)
    {
        low[Now] = ++dfn;
        for (int i = head[Now]; ~i; i = Edge[i].next)
        {
            int NowTo = Edge[i].to;

            if (NowTo == fa) continue;
            /*下降边*/
            if (!low[NowTo]) {
                dfs1(NowTo, Now);
            }
            low[Now] = std::min(low[Now], low[NowTo]);
        }
        SumeDCC[low[Now]]++;
    }

    void dfs2(int Now, int fa)
    {
        f[Now][0] = 1, f[Now][1] = Pow[SumeDCC[Now]] - 1;
        SumTree[Now] = 1;
        for (int i = head[Now]; ~i; i = Edge[i].next)
        {
            int NowTo = Edge[i].to;
            if (NowTo == fa) continue;
            dfs2(NowTo, Now);
            SumTree[Now] += SumTree[NowTo];

            int f0 = 0, f1 = 0;
            f0 = f[Now][0] * 2 % MOD * f[NowTo][0] % MOD;
            f1 = f[Now][1] * 2 % MOD * f[NowTo][0] % MOD;
            f1 = (f1 + f[Now][1] * f[NowTo][1] % MOD) % MOD;
            f1 = (f1 + f[Now][0] * f[NowTo][1] % MOD) % MOD;

            f[Now][0] = f0, f[Now][1] = f1;
        }

        if (Now == Col[1]) {
            Ans += f[Now][1] % MOD * Pow[m - SumTree[Now] + 1] % MOD;
            Ans %= MOD;
        }else {
            Ans += f[Now][1] % MOD * Pow[m - SumTree[Now]] % MOD;
            Ans %= MOD;
        }
    }

    struct node
    {
        int to, w;
        int next;
    } Edge[MAXM];
    int Edge_Cnt = 0;
    int head[MAXN];
    void head_init() { for (int i = 0; i <= n + 1; i++) head[i] = -1; }

    inline void addedge(int u, int v) {
        Edge[++Edge_Cnt].to = v, Edge[Edge_Cnt].w = 1;
        Edge[Edge_Cnt].next = head[u];
        head[u] = Edge_Cnt;
    }
} Graph1, Graph2;

class Sol_Class
{
private:
    int cnt = 0;

public:
    /*e-DCC 缩点*/
    void eDCC()
    {
        Graph1.dfs1(1, -1);
        for (int i = 1; i <= n; i++) {
            Col[i] = low[i];
        }

        Graph2.head_init();
        for (int i = 1; i <= n; i++) {
            int u = Col[i];
            for (int j = Graph1.head[i]; ~j; j = Graph1.Edge[j].next) {
                int v = Col[Graph1.Edge[j].to];
                if (u != v) Graph2.addedge(u, v); 
            }
        }
    }

    /*树形 dp*/
    void solve()
    {
        Graph2.dfs2(Col[1], -1);
        printf("%lld", Ans);
    }
} Sol;

signed main()
{
    scanf("%lld %lld", &n, &m);
    Graph1.head_init();
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%lld %lld", &u, &v);

        Graph1.addedge(u, v);
        Graph1.addedge(v, u);
    }
    Pow[0] = 1;
    for (int i = 1; i <= 1e6; i++) {
        Pow[i] = (Pow[i - 1] * 2) % MOD; 
    }
    Sol.eDCC();
    Sol.solve();

    return 0;
}
2024/11/22 14:53
加载中...