hdu 6073 Matching In Multiplication

来源:互联网 发布:ubuntu win7双系统 编辑:程序博客网 时间:2024/05/16 07:58

题意:给出一个“二分图”,左边顶点的数目和右边相同,求这个二分图所有完美匹配的权值和。题目保证至少有一组完美匹配。
分析:如果图中存在度数为1的点,那么与这个点匹配的点就是确定的。用拓扑排序去除这些点之后,图中留下的一定是一个环,那么每隔一条边取一条就能构成完美匹配。

#include<cstdio>#include<vector>#include<queue>#include<cstring>#define mo 998244353using namespace std;const int maxn = 1e6;typedef unsigned long long ll;vector<ll> u[maxn];vector<ll> p[maxn];int d[maxn];int vis[maxn];ll n, m, k, p1, p2;void dfs(int k, int cnt, int fa){    for(int i = 0; i < u[k].size(); i++){        if(!vis[u[k][i]] && u[k][i] != fa){            vis[u[k][i]] = 1;            if(cnt & 1) (p1 *= p[k][i]) %= mo;            else (p2 *= p[k][i]) %= mo;            dfs(u[k][i], cnt+1, k);        }    }}int main(){//  freopen("1007.in","r",stdin);//  freopen("data1.out","w",stdout);    int T;    scanf("%d", &T);    while(T--){        memset(vis, 0, sizeof(vis));        memset(d, 0, sizeof(d));        long long ans = 1;        scanf("%llu", &n);        for(int i = 1; i <= 2*n; i++) {            u[i].clear();            p[i].clear();        }        for(int i = 1; i <= n; i++){            for(int j = 1; j <= 2; j++){                ll x, w;                scanf("%llu%llu", &x, &w);                d[x + n]++;                u[i].push_back(x + n);                p[i].push_back(w);                u[x + n].push_back(i);                p[x + n].push_back(w);            }               d[i] = 2;        }        for(int i = n + 1; i <= 2 * n; i++){            if(u[i].size() == 1){                vis[i] = 1, d[i] = 0;                queue<int> q;                   q.push(i);                while(!q.empty()){                    int t = q.front();                    q.pop();                    for(int j = 0; j < u[t].size(); j++){                        if(vis[u[t][j]] != 1){                            d[u[t][j]]--;                            if(t > n) (ans *= p[t][j]) %= mo;                            if(d[u[t][j]] == 1){                                vis[u[t][j]] = 1;                                q.push(u[t][j]);                            }                         }                    }                }            }        }        for(int i = 1; i <= n; i++){            if(!vis[i]){                p1 = p2 = 1;                dfs(i, 1, i);                ans = ans * ((p1 + p2) % mo) % mo;            }        }        printf("%llu\n", ans);    }    return 0;}