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;
}