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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(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
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判断的,感觉都差不多。。。。

 














以上是关于HDU 6073 Matching In Multiplication —— 2017 Multi-University Training 4的主要内容,如果未能解决你的问题,请参考以下文章

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

hdu 6073

HDU - 6975 Forgiving Matching(多项式匹配字符串)

HDU6799 Parentheses Matching(贪心/括号匹配)

HDU1306 String Matching 暴力

HDU 6629 string matching(拓展kmp)