HDU 6073 Matching In Multiplication (二分图)

Description

给出一个点集为U和V的二分图,满足如下条件,|U|=|V|=n,U中的每个点都有两条边,没有重边,保证至少存在一个完美匹配。每条边有一个权重,定义一个完美匹配的权重是这个匹配中所有所有边的权值的乘积,求所有完美匹配的权重的和。

Input

第一行给出用例组数T,对于每个用例,第一行给出一个整数n,表示U集合的大小,接下来有n行,每行4个数,第i行vi

Output

Sample Input

1
2
2 1 1 4
1 4 2 3

Sample Output

16

Solution

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll mod = 998244353;
const int N = 3e5 + 10;

struct Edge
{
    int to, w, next;
    Edge() {}
    Edge(int to, int w, int next): to(to), w(w), next(next) {}
} edge[4 * N];
int adj[2 * N], no;

void init()
{
    memset(adj, -1, sizeof(adj));
    no = 0;
}
void add(int u, int v, int w)
{
    edge[no] = Edge(v, w, adj[u]);
    adj[u] = no++;
}

int deg[2 * N], deg1[2 * N], t;
bool vis[2 * N];
ll x, y;

void go(int start)
{
	int u = start;
	vis[u] = true;
    while (true)
    {
        int v = -1;
        for (int i = adj[u]; i != -1; i = edge[i].next)
            if (!vis[edge[i].to])
            {
                v = edge[i].to;
                x = x * edge[i].w % mod;
                vis[v] = true;
                break;
            }
		u = -1;
        for (int i = adj[v]; i != -1; i = edge[i].next)
            if (!vis[edge[i].to])
            {
                u = edge[i].to;
                y = y * edge[i].w % mod;
                vis[u] = true;
                break;
            }
		if (u != -1) continue;
		{
			for (int i = adj[v]; i != -1; i = edge[i].next)
				if (edge[i].to == start)
				{
					y = y * edge[i].w % mod;
					break;
				} 
			break;
		}
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        init();
        memset(deg, 0, sizeof(deg));
        for (int u = 1; u <= n; u++)
        {
            int v, w;
            scanf("%d%d", &v, &w);
            v += n;
            add(u, v, w); add(v, u, w);
            deg[v]++;
            scanf("%d%d", &v, &w);
            v += n;
            add(u, v, w); add(v, u, w);
            deg[v]++;
        }
        t = 0;
        for (int i = n; i <= 2 * n; i++)
            if (deg[i] == 1) deg1[++t] = i;
        memset(vis, false, sizeof(vis)); 
        ll ans = 1;
        while (t)
        {
            int v = deg1[t--];
			if (vis[v]) continue;
            vis[v] = true;
            int u;
            for (int i = adj[v]; i != -1; i = edge[i].next)
                if (!vis[edge[i].to])
                {
                    u = edge[i].to;
                    ans = ans * edge[i].w % mod;
                    vis[u] = true;
                    break;
                }
            for (int i = adj[u]; i != -1; i = edge[i].next)
                if (!vis[edge[i].to])
                {
                    int v = edge[i].to;
                    deg[v]--;
                    if (deg[v] == 1) deg1[++t] = v;
                }
        }
        for (int i = 1; i <= n; i++)
            if (!vis[i]) 
			{
				x = 1; y = 1;
				go(i);
				ans = ans * ((x + y) % mod) % mod;
			}
        printf("%lld\n", ans);
    }
    return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=6073

posted @ 2017-08-06 14:50  达达Mr_X  阅读(243)  评论(0编辑  收藏  举报