HDU 6073 Matching In Multiplication —— 2017 Multi-University Training 4

Matching In Multiplication

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1389    Accepted Submission(s): 423

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.

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.

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

题意:左右两边各有n个顶点的集合,分别为U,V,从U的每个顶点会有连出两条带权边与V的顶点相连。题目要求我们选取若干条边,使两个集合的所有点得到覆盖,并且定义这种情况为“完美匹配“,”完美匹配“的值为所选取的边权值求积,最后输出所有完美匹配的值之和。

思路:首先对于V的所有点来说,入度为1的点一定在U集合有唯一的点与之相连,在每种”完美匹配“里它们的配对是固定的,于是就可以扫一遍所有唯一对应的点对,求出它们的边权之积 left。

在排除以上情况的点之后,U集合点的出度均为2,假如V集合存在入度大于2的点,必存在另外有个点入度小于2。然而这是不可能的,否则就和上一种情况矛盾。所以剩余V集合里的点入度均为2,剩余的边构成了环。接着间隔取点,每个环的”完美匹配“结果分两种s[0], s[1],求出所有s[0]+s[1], 与left相乘取模得到结果。(补题时没好好理解题意,把相乘写成相加了(/TДT)/)

AC代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<vector>
  5 #include<fstream>
  6 #include<queue>
  7 using namespace std;
  8 typedef long long LL;
  9 const int MAXN=6e5+10;
 10 const int N=3e5;
 11 const LL MOD=998244353;
 12 struct Edge{
 13     int to;
 14     LL w;
 15 };
 16 vector<Edge> edge[MAXN];
 17 int deg[MAXN];
 18 LL s[2];
 19 void dfs(int node,int pos, bool ext){
 20     //cout<<node<<‘ ‘<<s[0]<<‘ ‘<<s[1]<<‘ ‘<<deg[node]<<‘ ‘<<ext<<endl;
 21     for(int i=0;i<edge[node].size();i++){
 22         int p=edge[node][i].to;
 23         if(!deg[p])
 24             continue;
 25
 26         if(deg[p]==2)
 27         {
 28             deg[node]--;
 29             deg[p]--;
 30             s[pos]=s[pos]*edge[node][i].w%MOD;
 31             dfs(p, pos^1, ext);
 32             break;
 33         }
 34         else if(deg[node]==1&&deg[p]==1)
 35         {
 36             if(ext==false)
 37                 ext=true;
 38             else{
 39                 deg[node]--;
 40                 deg[p]--;
 41                 s[pos]=s[pos]*edge[node][i].w%MOD;
 42                 return;
 43             }
 44         }
 45     }
 46 }
 47
 48 int main()
 49 {
 50     //ifstream cin("ylq.txt");
 51     int T;
 52     cin>>T;
 53     int n,v1,v2;
 54     LL w1,w2;
 55     Edge e1,e2;
 56     while(T--)
 57     {
 58         memset(deg, 0, sizeof(deg));
 59         //cin>>n;
 60         scanf("%d", &n);
 61         for(int i=1;i<=N+n;i++){
 62             edge[i].clear();
 63         }
 64         for(int i=1;i<=n;i++){
 65             //cin>>v1>>w1>>v2>>w2;
 66             scanf("%d %lld %d %lld", &v1, &w1, &v2, &w2);
 67             deg[v1+N]++;
 68             deg[v2+N]++;
 69             deg[i]+=2;
 70
 71             e1.to=v1+N;e1.w=w1;
 72             e2.to=v2+N;e2.w=w2;
 73             edge[i].push_back(e1);
 74             edge[i].push_back(e2);
 75
 76             e1.to=i;e2.to=i;
 77             edge[v1+N].push_back(e1);
 78             edge[v2+N].push_back(e2);
 79         }
 80
 81         LL left=1;
 82         queue<int> q;
 83         for(int i=N;i<=n+N;i++)
 84             if(deg[i]==1)
 85                 q.push(i);
 86
 87         int m;
 88         while(!q.empty())
 89         {
 90             int p, pp;
 91             m=q.front(); q.pop();
 92             deg[m]=0;
 93             for(int i=0;i<edge[m].size();i++){
 94                 p=edge[m][i].to;
 95                 if(!deg[p])
 96                     continue;
 97                 else
 98                 {
 99                     deg[p]=0;
100                     left=left*edge[m][i].w%MOD;
101                     for(int k=0;k<edge[p].size();k++){
102                         pp=edge[p][k].to;
103                         if(deg[pp]==0) continue;
104
105                         deg[pp]--;
106                         if(deg[pp]==1)
107                             q.push(pp);
108                     }
109                 }
110             }
111
112         }
113         //cout<<‘*‘<<left<<‘*‘<<endl;
114         LL ans=left;
115         for(int i=1;i<=n;i++){
116             if(!deg[i])
117                 continue;
118             s[0]=s[1]=1;
119             dfs(i, 1, 0);
120             ans=ans*(s[0]+s[1])%MOD;
121         }
122
123         printf("%lld\n", ans);
124     }
125 }

我的代码里用入度出度判断是否走到重复点,看了好多人都是用vis判断的,感觉都差不多。。。。

时间: 2024-10-03 21:41:39

HDU 6073 Matching In Multiplication —— 2017 Multi-University Training 4的相关文章

HDU 6073 Matching In Multiplication dfs遍历环 + 拓扑

Matching In Multiplication Problem DescriptionIn 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

HDU 6073 Matching In Multiplication(拓扑排序)

Matching In Multiplication Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1127    Accepted Submission(s): 325 Problem Description In the mathematical discipline of graph theory, a bipartite g

HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9

/* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问两串是否匹配 分析: dp[i][j] 代表B[i] 到 A[j]全部匹配 然后根据三种匹配类型分类讨论,可以从i推到i+1 复杂度O(n^2) */ #include <bits/stdc++.h> using namespace std; const int N = 2505; int t;

HDU 6168 - Numbers | 2017 ZJUT Multi-University Training 9

/* HDU 6168 - Numbers [ 思维 ] | 2017 ZJUT Multi-University Training 9 题意: .... 分析: 全放入multiset 从小到大,慢慢筛 */ #include <bits/stdc++.h> using namespace std; const int N = 125250; int n, s[N]; int a[N], cnt; multiset<int> st; multiset<int>::it

矩阵乘法 --- hdu 4920 : Matrix multiplication

Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 820    Accepted Submission(s): 328 Problem Description Given two matrices A and B of size n×n, find the product of them. b

HDU 6058 Kanade&#39;s sum —— 2017 Multi-University Training 3

Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2512    Accepted Submission(s): 1045 Problem Description Give you an array A[1..n]of length n. Let f(l,r,k) be the k-th largest eleme

hdu 5164 Matching on Array (用map实现的ac自动机)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5164 题意: 给出长度为n一个母串,给出m个长度为ki子串,匹配的条件是比率相同,如子串4 8 能和 1 2 4匹配.问所有子串在母串中出现多少次. 限制: 1 <= n,m <= 1e5 1 <= ki <= 300000 思路: 赤裸裸的ac自动机啊,不过next数组用map来实现,出题人脑洞真大. 这里有一点还要注意,hdu的g++,结构体里面不能开太大的东西,要不然他ce了还

HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)

题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能)  第2为表示能不能构成2 ...  这样用d[1<<n] 的DP  像背包那样背 n次就可以 最后状态中第k位为1的就可以加上方法数. #include<cstring> #include<cstdio> #include<cmath> #include <

HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

题意:给定n*m个格子,每个格子能填0-k 的整数.然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案. 思路:网络流,一共 n+m+2个点   源点 到行连流量为 所给的 当前行之和.    每行 连到每一列 一条流量为  k的边,每列到汇点连 列和.如果流量等于总和则有解,反之无解(如果列总和不等于行总和也无解).  判断方案是否唯一 找残留网络是否存在长度大于2的环即可,有环说明不唯一. #include<cstdio> #include<cstring&