zoukankan      html  css  js  c++  java
  • 2017 Multi-University Training Contest

    链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1007&cid=762

    题意:给定一个二分图,由U、V两部分组成,两部分大小相同,且U中每个点都连向V中的两个点,每个完美匹配的权定义为匹配中的边乘积,求所有完美匹配的权之和。

    分析:考虑V中的点,因为题目说了至少有一个完美匹配,所有V中度最少的点至少有一条边,最多两条,如果是一条,它只有一种连法,把对应U中的点删掉,重复以上步骤,最少的那个有两条,那么V中每个点都连两条,整个图由若干个环组成,每个环对应两个匹配,然后乘法一下就得到答案了。。图论的题不打模板就写得很啰嗦。。

      1 #include<iostream>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<vector>
      5 #include<cstring>
      6 using namespace std;
      7 typedef long long ll;
      8 const int maxn=3e5+5,mod=998244353;
      9 struct Vertex{
     10     int c,order;
     11     Vertex(int c,int order){
     12         this->c=c;this->order=order;
     13     }
     14 };
     15 bool operator<(Vertex a,Vertex b){
     16     return a.c>b.c;
     17 }
     18 priority_queue<Vertex> q;
     19 struct Edge{
     20     int s,t,w;
     21     Edge(int s,int t,int w){
     22         this->s=s;this->t=t;this->w=w;
     23     }
     24     Edge(){}
     25 };
     26 bool Is_delete[maxn*2];
     27 vector<Edge>edge;
     28 vector<int> u[maxn],v[maxn];
     29 int coun[maxn],n;
     30 void AddEdge(int s,int t,int w){
     31     u[s].push_back(edge.size());
     32     v[t].push_back(edge.size());
     33     edge.push_back(Edge(s,t,w));
     34 }
     35 ll product=1,ans=1;
     36 void init(){
     37     while(!q.empty())q.pop();
     38     edge.clear();
     39     for(int i=1;i<=n;i++){
     40         u[i].clear();v[i].clear();
     41     }
     42     memset(Is_delete,0,sizeof(Is_delete));
     43     product=1;ans=1;
     44 }
     45 void solve(){
     46     int countc=0;
     47     for(int i=1;i<=n;i++){
     48         q.push(Vertex(v[i].size(),i));
     49         coun[i]=v[i].size();
     50     }
     51     while(1){
     52         Vertex h=q.top();
     53         q.pop();
     54         if(h.c==2)break;
     55         for(int i=0;i<v[h.order].size();i++){
     56             if(Is_delete[v[h.order][i]])continue;
     57             Is_delete[v[h.order][i]]=true;
     58             product=(product*edge[v[h.order][i]].w)%mod;
     59             int tt=v[h.order][i];
     60             int s=edge[v[h.order][i]].s;
     61             for(int i=0;i<2;i++){
     62                 if(edge[u[s][i]].t==h.order)continue;
     63                 if(!Is_delete[u[s][i]]){
     64                     h.c=--coun[edge[u[s][i]].t];
     65                     h.order=edge[u[s][i]].t;
     66                     q.push(h);
     67                 }
     68                 Is_delete[u[s][i]]=true;
     69             }
     70             break;
     71         }
     72     }
     73     while(1){
     74         countc++;
     75         int start,s=-1,t;
     76         ll pro=1,ppro=1;
     77         for(int i=0;i<edge.size();i++){
     78             if(!Is_delete[i]){
     79                 s=start=edge[i].s;
     80                 t=edge[i].t;break;
     81             }
     82         }
     83         if(s==-1)break;
     84         while(1){
     85             for(int i=0;i<u[s].size();i++){
     86                 if(!Is_delete[u[s][i]]){
     87                     pro=(pro*edge[u[s][i]].w)%mod;
     88                     t=edge[u[s][i]].t;
     89                     Is_delete[u[s][i]]=true;
     90                     break;
     91                 }
     92             }
     93             for(int i=0;i<v[t].size();i++){
     94                 if(!Is_delete[v[t][i]]){
     95                     s=edge[v[t][i]].s;
     96                     ppro=(ppro*edge[v[t][i]].w)%mod;
     97                     Is_delete[v[t][i]]=true;
     98                     break;
     99                 }
    100             }
    101             if(s==start)break;
    102         }
    103         ans=(ans*(ppro+pro))%mod;
    104     }
    105     ans=(product*ans)%mod;
    106 }
    107 int main(){
    108     //freopen("e:\in.txt","r",stdin);
    109     int t,v1,v2,w1,w2;
    110     scanf("%d",&t);
    111     while(t--){
    112         init();
    113         scanf("%d",&n);
    114         for(int i=1;i<=n;i++){
    115             scanf("%d%d%d%d",&v1,&w1,&v2,&w2);
    116             AddEdge(i,v1,w1);
    117             AddEdge(i,v2,w2);
    118         }
    119         solve();
    120         cout<<ans<<endl;
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    获取Mac地址
    GbkToUtf8 Utf8ToGbk PackHttp
    first Automation
    win32 Dll 中添加afx.h 出现如下错误 error LNK2005: _DllMain@12 already defined
    OpenSUSE 开启SSH 和网络设置
    systemctl命令用法详解
    浅谈Python的列表和链表
    用Python实现最大堆
    写一个解二阶魔方的程序
    暴力破解SixPack问题
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7282531.html
Copyright © 2011-2022 走看看