Matching In Multiplication(HDU 6073)

来源:互联网 发布:三菱plc编程实例 编辑:程序博客网 时间:2024/06/05 11:31

Matching In Multiplication

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


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(1T15), denoting the number of test cases.

In each test case, there is an integer n(1n300000) 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(1vi,jn,1wi,j109), 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
122 1 1 41 4 2 3
 

Sample Output
16


 //题意:一张二分图,左边每个点都是2个出度(即左边每个点都和右边的点有2条边),右边就不一定了。每2个点连一条边(一个点在左边,一个点在右边),若包含左右所有顶点,就是完美匹配。一个完美匹配的值是各边权值的乘积。现在要求所有完美匹配的值之和。

//思路:很显然,如果一个点只有1条边连向它,那么要构成完美匹配的话,这条边就一定是其中一条,(即这个点的配对点是唯一的)。且这种点一定出现在右边。先把这种情况都找出来,对于后面所有情况来说,都要包含这条边。
设满足这个条件的所有边的乘积为res。

把上述条件的那些边删去后,剩下的每个点(包括左右)必定有2条边经过。但现在的图中可能有多个环。但我们知道,在一个环中只有2种情况,设一种情况的值是v1,另一种是v2,那这个环的值就是v1+v2。我们要找出所有环,把所有环的值相乘,设为ans。

那么答案就是(ans*res)%mod

给几组我调试的数据:

3
1 1 2 2
1 3 3 4
1 5 3 6
输出:76

4
1 4 2 1
1 4 2 3
3 4 4 1
3 4 4 3
输出:256

4
1 2 2 2
2 1 3 2
2 1 4 2
2 1 4 2
输出:16

6
1 2 2 3
2 1 3 2
2 2 3 4
3 3 4 2
5 1 6 4
5 3 6 2
输出:448

3
1 2 2 3
2 4 3 5
1 6 3 7
输出:146

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <vector>#include <queue>#include <algorithm>using namespace std;const int MAX = 600005;const int mod = 998244353;typedef struct {int val, to;}Point;int n;long long sum;vector<Point>map[MAX];int vis[MAX];int vis2[MAX];int point[MAX];void work(){for (int i = 1; i <= n; i++)vis[i] = 1;//计算并删去只有1条边经过的点的情况int ok;while (true){int i;ok = 0;for (i = n + 1; i <= 2 * n; i++){if (map[i].size() == 1){ok = 1;int v = map[i][0].to;vis[v] = 0;sum = (sum * 1LL * map[i][0].val) % mod;map[i].clear();for (int j = 0; j < map[v].size(); j++){if (map[v][j].to != i){int u = map[v][j].to;for (int k = 0; k < map[u].size(); k++){if (map[u][k].to == v){map[u].erase(map[u].begin() + k);break;}}break;}}map[v].clear();}}if (ok == 0)break;}while (true){queue<int>q;long long ans = 0, cnt;int w, i;for (i = 1; i <= n; i++){if (vis[i] == 1){w = i;vis[i] = 0;break;}}if (i == n + 1)break;//找环int num = 0;point[num++] = w;q.push(w);memset(vis2, 0, sizeof(vis2));while (!q.empty()){int now = q.front();q.pop();for (i = 0; i < map[now].size(); i++){if (map[now][i].to <= n && vis[map[now][i].to]==1){vis[map[now][i].to] = 0;point[num++] = map[now][i].to;q.push(map[now][i].to);}else if (map[now][i].to > n && vis2[map[now][i].to - n] == 0){vis2[map[now][i].to - n] = 1;q.push(map[now][i].to);}}}//计算环值for (i = 0; i < map[point[0]].size(); i++){cnt = 1;cnt = (cnt * 1LL * map[point[0]][i].val) % mod;int xx = map[point[0]][i].to;int aim = point[0];while (true){int now, temp;for (int j = 0; j < map[xx].size(); j++){if (map[xx][j].to != aim){now = map[xx][j].to;break;}}if (now == point[0])break;for (int j = 0; j < map[now].size(); j++){if (map[now][j].to != xx){cnt = (cnt * 1LL * map[now][j].val) % mod;temp = map[now][j].to;}}aim = now;xx = temp;}ans = (ans + cnt) % mod;}sum = (sum*ans) % mod;}}int main(){int T;scanf("%d", &T);while (T--){scanf("%d", &n);for (int i = 0; i <= 2*n; i++)map[i].clear();int v1, w1, v2, w2;for (int i = 1; i <= n; i++){scanf("%d%d%d%d", &v1, &w1, &v2, &w2);//边是无向边,右边的点设为n+iPoint a;a.val = w1;a.to = v1 + n;map[i].push_back(a);a.to = i;map[v1 + n].push_back(a);a.val = w2;a.to = v2 + n;map[i].push_back(a);a.to = i;map[v2 + n].push_back(a);}sum = 1;work();printf("%lld\n", sum%mod);}return 0;} 



阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 念佛号时心老是不集中怎么办 扑lv期嗓子痛头痛怎么办 公众号忘记了账号怎么办 公众号账号密码忘记了怎么办 现实生活被小人缠上怎么办 五行缺木和水怎么办 八字火旺的人怎么办 综合旺衰得分负怎么办 妈妈误打死一只黄鼠狼怎么办 油笔画在白墙上怎么办 壁纸上的水彩笔怎么办 隐形拉链头脱了怎么办 拉链的一边掉了怎么办 帝豪gs加了乙醇汽油怎么办 命理五行缺木怎么办 微信改名含有特殊符号怎么办 户口名字打错了怎么办 寻仙会心几率差怎么办 注册商标下来了没收到怎么办 金融公司倒闭欠的钱怎么办 买车贷款被骗了怎么办 定投终止后钱怎么办 受到小贷公司催款威胁怎么办 合同保证金单据丢了怎么办 公司注销期间发现欠税怎么办 公司注销后银行账户怎么办 注销公司营业执照和公章丢失怎么办 工商核名过期了怎么办 核名后的许可没办下来怎么办 重庆公司核名有同名的怎么办 新电视不全屏怎么办左右有黑边 所学类别找不到音乐表演怎么办 公司口头通知不续签合同怎么办 雪纺衬衣皱了怎么办 狗打架受伤怎么办泰迪 大狗打架破了怎么办 舌头上长溃疡怎么办吃什么药 悠悠球不回弹怎么办啊 围棋遇到对方不停围堵怎么办? s围棋业余四段想提升怎么办 wps禁止创建分享链接怎么办