Matching In Multiplication
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1425 Accepted Submission(s): 436
Problem Description
In the mathematical discipline of graph theory, a bipartite graph is a graph whose vertices can be divided into two disjoint sets
U
and
V
(that is,
U
and
V
are each independent sets) such that every edge connects a vertex in
U
to one in
V
. Vertex sets
U
and
V
are usually called the parts of the graph. Equivalently, a bipartite graph is a graph that does not contain any odd-length cycles. A matching in a graph is a set of edges without common vertices. A perfect matching is a matching that each vertice is covered by an edge in the set.
Little Q misunderstands the definition of bipartite graph, he thinks the size of U is equal to the size of V , and for each vertex p in U , there are exactly two edges from p . Based on such weighted graph, he defines the weight of a perfect matching as the product of all the edges' weight, and the weight of a graph is the sum of all the perfect matchings' weight.
Please write a program to compute the weight of a weighted ''bipartite graph'' made by Little Q.
![](https://i-blog.csdnimg.cn/blog_migrate/d538268b0a67d2b02fa9553c081a95b8.jpeg)
Little Q misunderstands the definition of bipartite graph, he thinks the size of U is equal to the size of V , and for each vertex p in U , there are exactly two edges from p . Based on such weighted graph, he defines the weight of a perfect matching as the product of all the edges' weight, and the weight of a graph is the sum of all the perfect matchings' weight.
Please write a program to compute the weight of a weighted ''bipartite graph'' made by Little Q.
Input
The first line of the input contains an integer
T(1≤T≤15)
, denoting the number of test cases.
In each test case, there is an integer n(1≤n≤300000) in the first line, denoting the size of U . The vertex in U and V are labeled by 1,2,...,n .
For the next n lines, each line contains 4 integers vi,1,wi,1,vi,2,wi,2(1≤vi,j≤n,1≤wi,j≤109) , denoting there is an edge between Ui and Vvi,1 , weighted wi,1 , and there is another edge between Ui and Vvi,2 , weighted wi,2 .
It is guaranteed that each graph has at least one perfect matchings, and there are at most one edge between every pair of vertex.
In each test case, there is an integer n(1≤n≤300000) in the first line, denoting the size of U . The vertex in U and V are labeled by 1,2,...,n .
For the next n lines, each line contains 4 integers vi,1,wi,1,vi,2,wi,2(1≤vi,j≤n,1≤wi,j≤109) , denoting there is an edge between Ui and Vvi,1 , weighted wi,1 , and there is another edge between Ui and Vvi,2 , weighted wi,2 .
It is guaranteed that each graph has at least one perfect matchings, and there are at most one edge between every pair of vertex.
Output
For each test case, print a single line containing an integer, denoting the weight of the given graph. Since the answer may be very large, please print the answer modulo
998244353
.
Sample Input
1 2 2 1 1 4 1 4 2 3
Sample Output
16
Source
题意:给你一个二分图,集合U和V各有n个点,集合U的每个点都连出两条边。保证至少有一个完美匹配。对于一个完美匹配,价值是边权之积,要求所有完美匹配的价值和
解题思路:如果一个点的度数为1的话,那么它的匹配方案肯定是固定的,可以先通过拓扑排序去掉集合V中度数为1的点,对V中度数为1的点都在U中找一个点与之匹配。那么这些对答案ans的贡献为ans*唯一对应边的边权。这样处理完后,由于集合U和集合V中点的度数都必然为2,并且图中的每个连通块肯定都成环。那么只需要对每个连通块间隔取边权,每个连通块的完备匹配权值为ans1[0],ans1[1],则该连通块对ans的贡献为ans*(ans1[0]+ans1[1])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
const LL mod = 998244353;
int n, v1, v2, w1, w2;
int vis[600009], in[600009];
vector<pair<int, int>>g[600009];
LL ans1[2];
void dfs(int k, int fa, int flag,int s)
{
vis[k] = 1;
for (int i = 0; i < g[k].size(); i++)
{
if (g[k][i].first == s&&g[k][i].first != fa) ans1[flag] = 1LL*ans1[flag] * g[k][i].second%mod;
if (vis[g[k][i].first]) continue;
ans1[flag] = 1LL * ans1[flag] * g[k][i].second%mod;
dfs(g[k][i].first, k, flag ^ 1, s);
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= 2 * n; i++) g[i].clear(), vis[i] = in[i] = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d%d%d%d", &v1, &w1, &v2, &w2);
g[i].push_back(make_pair(v1 + n, w1));
g[i].push_back(make_pair(v2 + n, w2));
g[v1 + n].push_back(make_pair(i, w1));
g[v2 + n].push_back(make_pair(i, w2));
in[i] = 2, in[v1 + n]++, in[v2 + n]++;
}
queue<int>q;
for (int i = n + 1; i <= 2 * n; i++)
if (in[i] == 1) q.push(i), vis[i] = 1;
LL ans = 1;
while (!q.empty())
{
int pre = q.front();
q.pop();
for (int i = 0; i < g[pre].size(); i++)
{
if (vis[g[pre][i].first]) continue;
if (--in[g[pre][i].first] == 1) q.push(g[pre][i].first), vis[g[pre][i].first] = 1;
if (pre > n) ans = 1LL*ans*g[pre][i].second%mod;
}
}
for (int i =1; i <= n; i++)
{
if (vis[i]) continue;
ans1[0]=ans1[1]=1;
dfs(i, 0, 0, i);
ans = (ans*(ans1[0] + ans1[1]) % mod) % mod;
}
printf("%lld\n", ans);
}
return 0;
}