zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    124     }
    125 }

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

     
  • 相关阅读:
    咖啡叫软件开发--界面组日志06-总结
    咖啡叫软件开发--界面组日志05
    咖啡叫软件开发--界面组日志04
    咖啡角软件开发--界面组日志03
    咖啡角软件开发--界面组日志02
    咖啡角软件开发--界面组日志01
    实时控制软件 第三次作业
    第二次作业
    《构建之法:现代软件工程》第一章有感
    第一天
  • 原文地址:https://www.cnblogs.com/MasterSpark/p/7295808.html
Copyright © 2011-2022 走看看