题意: 给出一个二部图,U、V分别是二部图的两个点集,其中,U中每个点会有两条边连到V中两个不同的点。

  完美匹配定义为:所有点都成功匹配。

  思路:已知一定是完美匹配了呀(也一定存在),我们先把度数为一的匹配了(用拓扑把度数为一的找出来),那么剩下的图中左右各有m个点,每个点度数都不小于2,且左边每个点度数都是2,而右侧总度数是2m,因此右侧只能是每个点度数都是2。这说明这个图每个连通块是个环,在环上间隔着取即可,一共两种方案。

   然后就完了(还是看了别人的才懂得ε=ε=ε=┏(゜ロ゜;)┛)。
/*  gyt
Live up to every day */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include <time.h>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 6e5+;
const int maxm=+;
const ll mod = ;
const int INF = 0x3f3f3f;
const db eps = 1e-;
struct node {
ll w;
int v, next;
}edge[maxn<<];
int no, head[maxn];
int bad[maxn], deg[maxn], vis[maxn];
int n, nn;
queue<int>q;
vector<int>vtt;
ll ans, must; void init() {
no=;
memset(vis, , sizeof(vis));
memset(head, -, sizeof(head));
memset(bad, , sizeof(bad));
memset(deg, , sizeof(deg));
}
void add(int u, int v, int w) {
edge[no].v=v; edge[no].next=head[u];
edge[no].w=w; head[u]=no++;
}
ll dfs(int cur, int father) {
vtt.push_back(cur);
vis[cur] = ;
for(int k = head[cur], kk; k != -; k = edge[k].next) {
int v = edge[k].v;
if(v == father) continue;
if(bad[v] || vis[v]) continue;
vis[v] = ; vtt.push_back(v);
for(kk = head[v]; kk != -; kk = edge[kk].next) {
if(!bad[edge[kk].v] && edge[kk].w != cur)
break;
}
return dfs(edge[kk].v, v)*edge[k].w%mod;
}
return ;
}
void solve() {
init(); scanf("%d", &n);
nn=n*;
for (int i=; i<=n; i++) {
int v, w; scanf("%d%d", &v, &w);
add(i, n+v, w); add(n+v, i, w);
deg[i]++, deg[n+v]++;
scanf("%d%d", &v, &w);
add(i, n+v, w); add(n+v, i, w);
deg[i]++, deg[n+v]++;
}
must=;
while(!q.empty()) q.pop();
for (int i=; i<=n; i++) {
if (deg[n+i]==) q.push(n+i); //把度数为一的提出来
}
while(!q.empty()) {
int u=q.front(); q.pop();
bad[u]=;
for (int k=head[u]; ~k; k=edge[k].next) { //找到度数为一的点连的另一个点a
int v=edge[k].v;
if (bad[v]) continue;
must=must*edge[k].w%mod;
bad[v]=;
for (int kk=head[v]; ~kk; kk=edge[kk].next) {//把a相连的点找出来,如果减掉1还是1,说明他能匹配的也只能是一个
if (bad[edge[kk].v]) continue;if (--deg[edge[kk].v]==) {
q.push(edge[kk].v);
}
}
}
}
ans=must;
//cout<<ans<<endl;
for (int i=; i<=n; i++) {
if (vis[i]||bad[i]) continue;
ll ans1=;
for(int k = head[i], kk; k != -; k = edge[k].next) {//分别两种匹配的结果
int v=edge[k].v;
vtt.clear();
vis[v]=;
for ( kk=head[v]; ~kk; kk=edge[kk].next) {
if (!bad[edge[kk].v] && edge[kk].v!=i) break;
}
ans1=(ans1+dfs(edge[kk].v, v)*edge[k].w%mod)%mod;
// cout<<ans1<<endl;
vis[v]=;
for (int j=; j<vtt.size(); j++) {
vis[vtt[j]]=;
}
vtt.push_back(v);
}
for (int j=; j<vtt.size(); j++) {
vis[vtt[j]]=;
}
ans = ans*ans1%mod;
}
printf("%lld\n", ans);
}
int main() {
int t = ;
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
scanf("%d", &t);
while(t--)
solve();
return ;
}
 

hdu 6073的更多相关文章

  1. HDU 6073 - Matching In Multiplication | 2017 Multi-University Training Contest 4

    /* HDU 6073 - Matching In Multiplication [ 图论 ] | 2017 Multi-University Training Contest 4 题意: 定义一张二 ...

  2. HDU 6073 Matching In Multiplication(拓扑排序+思维)

    http://acm.hdu.edu.cn/showproblem.php?pid=6073 题意:有个二分图,左边和右边的顶点数相同,左边的顶点每个顶点度数为2.现在有个屌丝理解错了最佳完美匹配,它 ...

  3. 2017 ACM暑期多校联合训练 - Team 4 1007 HDU 6073 Matching In Multiplication (模拟)

    题目链接 Problem Description In the mathematical discipline of graph theory, a bipartite graph is a grap ...

  4. HDU 6073 Matching In Multiplication(拓扑排序)

    Matching In Multiplication Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K ( ...

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

    Matching In Multiplication Problem DescriptionIn the mathematical discipline of graph theory, a bipa ...

  6. 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 ( ...

  7. hdu some problems in Multi-University Training Contest

    hdu 6103 Kirinriki #include<bits/stdc++.h> using namespace std; int n,m,ans; ]; void doit(int ...

  8. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

随机推荐

  1. JS 解决json字符串转换成json树形输出

    问题: 后台获取一个字符串,格式为  string +jsonList+string+..... 就是传过来一堆数据,然后其中包含了一个json格式的list, 我们希望能将它输出成树形结构显示,能够 ...

  2. JS获取鼠标左(右)滑事件

    鼠标左(右)滑也是网站开发中常见的效果之一,这里对鼠标左(右)滑做出一些解释. 首先要获取需要左右滑事件的节点: eg: var div=document.getElementById("d ...

  3. python 库安装方法及常用库

    python 库安装方法及常用库 python库安装方法: 方法一:setpu.py 1.下载库压缩包,解压,记录下路径:*:/**/……/ 2.运行cmd,切换到*:/**/……/目录下 3.运行s ...

  4. 转)服务器安装部署ESXI6.0

    1.制作一个ESXI6.0的系统安装盘 2.服务器启动后加载VMware ESXi 6.0的ISO文件,开始安装. 3.ESXi引导装入程序,VMware ESXi引导过程,在屏幕上方显示的版本号.内 ...

  5. 【linux C】C语言中常用的几个函数的总结【一】

    1.memset函数 定义变量时一定要进行初始化,尤其是数组和结构体这种占用内存大的数据结构.在使用数组的时候经常因为没有初始化而产生“烫烫烫烫烫烫”这样的野值,俗称“乱码”.每种类型的变量都有各自的 ...

  6. select-options and range

    1.SELECT...WHERE ... IN ...,它后面跟着的是一个RANGE类型的内表,这种内表是通过RANGES或者SELECT-OPTIONS来定义的. 2.内表中包含四个字段:SIGN, ...

  7. springmvc+logback项目的日志搭建

    一.重写HTMLLayout 两个自定义类:LzhHTMLLayoutBase和LzhHTMLLayout LzhHTMLLayoutBase代码如下: package top.liaozhengha ...

  8. PHP 依赖工具 monolog的使用

    <?phprequire 'vendor/autoload.php'; //自动加载类库 use Monolog\Logger;use Monolog\Handler\StreamHandler ...

  9. mysql left join 多条记录 1:n 的处理方法

    一.准备两张表,文章表和评伦表 CREATE TABLE `article` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', ...

  10. golang 创建一个简单的广播echo服务器

    package main; import ( "net" "fmt" "bufio" ) //里面的代码部分参考cmu440课程 //htt ...