zoukankan      html  css  js  c++  java
  • HDU 6073

    /*
    HDU 6073 - Matching In Multiplication [ 图论 ]  |  2017 Multi-University Training Contest 4
    题意:
    	定义一张二分图,U中每个节点和V中两个节点连边
    	完美匹配的权值为该匹配所有边的权值相乘
    	求所有完美匹配的权值之和
    分析:
    	可以发现有些V中的点只能连唯一的U中的点
    	按拓扑排序思路将这些全部处理掉后,剩下的点构成一个个环
    	每个环有两种连线方式,间隔取边权
    */
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int N = 600005;
    const LL MOD = 998244353;
    struct Edge {
        int v; LL w;
    };
    vector<Edge> G[N];
    int vis[N];
    int cnt[N];
    int t, n;
    LL ans;
    queue<int> que;
    LL s[2];
    void dfs(int x, int pre, int p)
    {
        if (vis[x]) return;
        vis[x] = 2;
        for (const auto & e : G[x])
        {
            if (vis[e.v] == 1 || e.v == pre) continue;
            s[p] = s[p] * e.w % MOD;
            dfs(e.v, x, p^1);
            break;
        }
    }
    void solve()
    {
        for (int i = n+1; i <= 2*n; i++)
            if (G[i].size() == 1) que.push(i);
        ans = 1;
        while (!que.empty())
        {
            int y = que.front(); que.pop();
            vis[y] = 1;
            for (const auto& e: G[y])
            {
                if (!vis[e.v])
                {
                    vis[e.v] = 1;
                    ans = ans * e.w % MOD;
                    for (const auto & ee: G[e.v])
                    {
                        if (vis[ee.v]) continue;
                        cnt[ee.v]--;
                        if (cnt[ee.v] == 1) que.push(ee.v);
                    }
                }
            }
        }
        for (int i = 1; i <= n; i++)
        {
            if (!vis[i])
            {
                s[0] = s[1] = 1;
                dfs(i, i, 0);
                ans = ans * (s[0] + s[1]) % MOD;
            }
        }
    }
    void init(int n)
    {
        for (int i = 0; i <= n; i++) G[i].clear();
        while (!que.empty()) que.pop();
        memset(vis, 0, sizeof(vis));
        memset(cnt, 0, sizeof(cnt));
    }
    int main()
    {
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d", &n);
            init(n<<1);
            for (int i = 1; i <= n; i++)
            {
                int v; LL w;
                scanf("%d%lld", &v, &w); v += n;
                G[i].push_back(Edge{v, w});
                G[v].push_back(Edge{i, w});
                cnt[v]++;
                scanf("%d%lld", &v, &w); v += n;
                G[i].push_back(Edge{v, w});
                G[v].push_back(Edge{i, w});
                cnt[v]++;
            }
            solve();
            printf("%lld
    ", ans);
        }
    }
    

      

  • 相关阅读:
    Web scraping tutorials with FMiner
    javascript
    Installing perl and writing your first perl program in Ubuntu
    c++
    sudo apt-get install libfcgi libfcgi-dev
    微信JSApi支付~订单号和微信交易号
    微信JSApi支付~坑和如何填坑
    WebApi系列~安全校验中的防篡改和防复用
    EF架构~CodeFirst自关联表的插入
    实时监控Cat之旅~对请求是否正常结束做监控(分布式的消息树)
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/7293883.html
Copyright © 2011-2022 走看看