题目中对二分图的定义十分特殊, 指的是 U,V两部分中,U的顶点度数必定为2,V中顶点无限制。

题目要求的是 对于所有匹配,该匹配的权值=该匹配中选中的边的边权的乘积,求所有匹配权值之和。

对于V中的顶点,a∈V , 如果a的度数为1, 那么a的最优匹配就已经决定了,此时将a对答案的贡献记录下来(ans乘上该边的权即可,因为任意一种匹配都必定包含此边)。

删去a点后,所有与a相连的顶点度数-1,如果这个时候又出现了度数为1的顶点,就重复类似a的操作,直到图中再无度数为1的顶点。

可以发现,这就是无向图判环的一种方法。剩下的顶点度数必定为2(题目中的特殊条件限制),且构成x个环。

对于每个环我们可以发现

都会只有两种取法使得最优匹配,这种跳着取边算贡献的过程我们可以用dfs实现。

题目中,一种 最优匹配的权值 是 最优匹配中所有边的乘积,所以对于一个环,我们算出 Sum蓝色=∏蓝色边  Sum红色=∏红色边

计算(Sum蓝色+Sum红色)与当前的ans相乘即可,因为任意 两个之间的最优匹配都可以随意配对 比如 环a红色配环b蓝色, 环a蓝色配 环b蓝色...

/*hdu6073[dfs+删边] 2017多校4*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD = 998244353LL;
struct Edge {
int to, cost;
Edge(int T = , int C = )
: to(T), cost(C) {}
};
vector<Edge>G[];
int deg[];
bool vis[];
int T, n, u, v, w;
LL x = , y = ;
LL res = , ans = ;
void init() {
res = , ans = ;
for (int i = ; i <= * n; i++) {
G[i].clear();
}
memset(deg, , sizeof(deg));
memset(vis, , sizeof(vis));
}
void dfs(int u, int fa, int c) {
if (vis[u]) return;
vis[u] = ;
for (int i = ; i < (int)G[u].size(); i++) {
Edge &e = G[u][i];
if (e.to == fa || deg[e.to] != ) continue;
dfs(e.to, u, c ^ );
if (c) x = (x * e.cost) % MOD;
else y = (y * e.cost) % MOD;
break;
}
return;
}
void solve() {
queue<int>q;
for (int i = ; i <= * n; i++) {
if (deg[i] == ) {
q.push(i);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
deg[u]--;
for (int i = ; i < (int)G[u].size(); i++) {
Edge &e = G[u][i];
deg[e.to]--;
if (!vis[e.to] && !vis[u]) {
vis[e.to] = vis[u] = ;
res = (res * e.cost) % MOD;
}
if (deg[e.to] == ) {
q.push(e.to);
}
}
}
memset(vis, , sizeof(vis));
for (int i = ; i <= * n; i++) {
if (deg[i] == && !vis[i]) {
x = , y = ;
dfs(i, i, );
//cout << x << ' ' << y << endl;
ans = (ans * (x + y)) % MOD;
}
}
ans = (ans * res) % MOD;
printf("%lld\n", ans);
}
int main() {
//freopen("1007.in", "r", stdin);
//freopen("1007.txt", "w", stdout);
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
init();
for (int i = ; i <= n; i++) {
scanf("%d%d", &v, &w);
G[i].push_back(Edge(v + n, w));
G[v + n].push_back(Edge(i, w));
deg[i]++, deg[v + n]++;
scanf("%d%d", &v, &w);
G[i].push_back(Edge(v + n, w));
G[v + n].push_back(Edge(i, w));
deg[i]++, deg[v + n]++;
}
solve();
}
return ;
}

hdu6073[dfs+删边] 2017多校4的更多相关文章

  1. hdu6035[dfs+思维] 2017多校1

    /*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; ; const ...

  2. hdu6060[贪心+dfs] 2017多校3

    /* hdu6060[贪心+dfs] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long L ...

  3. 2017 多校1 I Curse Myself

    2017 多校2 I Curse Myself(第k小生成树) 题目: 给一张带权无向连通图,该图的任意一条边最多只会经过一个简单环,定义\(V(k)为第k小生成树的权值和\),求出\(\sum_{k ...

  4. 2017 多校5 hdu 6093 Rikka with Number

    2017 多校5 Rikka with Number(数学 + 数位dp) 题意: 统计\([L,R]\)内 有多少数字 满足在某个\(d(d>=2)\)进制下是\(d\)的全排列的 \(1 & ...

  5. 2017 多校5 Rikka with String

    2017 多校5 Rikka with String(ac自动机+dp) 题意: Yuta has \(n\) \(01\) strings \(s_i\), and he wants to know ...

  6. 2017 多校4 Security Check

    2017 多校4 Security Check 题意: 有\(A_i\)和\(B_i\)两个长度为\(n\)的队列过安检,当\(|A_i-B_j|>K\)的时候, \(A_i和B_j\)是可以同 ...

  7. hdu6038[找规律+循环节] 2017多校1

    /*hdu6038[找规律+循环节] 2017多校1*/ #include<bits/stdc++.h> using namespace std; typedef long long LL ...

  8. hdu6074[并查集+LCA+思维] 2017多校4

    看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块 ...

  9. 2017 多校4 Wavel Sequence

    2017 多校4 Wavel Sequence 题意: Formally, he defines a sequence \(a_1,a_2,...,a_n\) as ''wavel'' if and ...

随机推荐

  1. HDU4405 Aeroplane chess(期望dp)

    题意 抄袭自https://www.cnblogs.com/Paul-Guderian/p/7624039.html 正在玩飞行棋.输入n,m表示飞行棋有n个格子,有m个飞行点,然后输入m对u,v表示 ...

  2. 修改输入框placeholder的默认样式

    一般网页中都用到input的placeholder属性,想让这个默认样式和网页保持一致,就需要重新设定样式,百度百度: :-moz-placeholder { / color: #000; opaci ...

  3. Azure Linux 云主机使用Root超级用户登录

    Azure的Linux虚拟机是可以灵活使用root超级用户的管理员权限的: 1:使用sudo passwd root指令设置超级用户root密码: 使用创建Linux时设置的用户名和密码登陆,使用su ...

  4. 最详细的github快速入门教程

    一:下载github 二:安装GitHub 下载之后点击 进行安装过程,安装之后桌面上会有两个图标,如下图 三:新建项目 GitHub是图形界面模式,Git Shell是命令行模式,在Windows系 ...

  5. 保存 http request 的数据到数据库表

    开发需求:把 http request 对象的数据保存到数据库中 第一步:编写 RequestInfoService 类,保存方法名是 saveRequestInfo // 保存request信息 p ...

  6. c#将本地文件上传至服务器(内网)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. 查看mysql已有用户并删除

    查看: SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user; 删除: drop us ...

  8. Could not load OpenSSL解决

    问题 Could not load OpenSSL. You must recompile Ruby with OpenSSL support or change the sources in you ...

  9. fluent_python1

    Magic Method python中有些跟对象本身有关的方法, 以两个下划线开始,两个下划线结束, 一般称为魔法方法(magic method). 比如 obj[key] 的背后就是 __geti ...

  10. Hibernate中get()与load()的区别,以及关于ThreadLocal的使用方法

    一.get方法和load方法的简易理解 (1)get()方法直接返回实体类,如果查不到数据则返回null.load()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象),但当代理对象被调用时 ...