当前位置: 首页 > news >正文

HDU-6073 Matching In Multiplication - 2017 Multi-University Training Contest - Team 4(拓扑+连通块处理)

题意:

"完美匹配"被认为是图中所有的点都被匹配的集合内的边所覆盖,一个"完美匹配"的权重是该匹配中所有边权的乘积,而一个"二分图"的权重是图中所有"完美匹配"的求和。

思路:

题目给的是二分图,但有一些限制,所以容易会想从二分图出发处理。实际上被骗了,由于左部的点度数都为2,所以去分析右部的点,发现当其度数等于1时,与其关联的边必选,所以需要以拓扑的思想去除所有这些度数为1的点及其相关联的左部的点及相应的边。然后剩余图就会是一个左部右部点数相同,且所有的点的度数都为2的图。

然后就去寻找图中的连通分量,寻找无向图的连通分量一般是去找点双连通分量,但这题不需要也不适用。事实上剩余图上所有连通的点就是一个连通分量,所以就又转化为了寻找连通块,并在寻找的过程中计算该连通块的方案值。寻找完连通块后,每一个连通块能贡献出两个值,再根据加法的结合率乘法的分解率,得到答案就等于每个连通块的两个值相加和后的乘积,再乘上必须选择的方案值(度数为1的点所造成的)即可。


代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod = 998244353;
const int maxn = 6e5+5;
struct node
{
	LL w;
	int v, next;
} edge[maxn*2];
int no, head[maxn];
int bad[maxn], deg[maxn];	//bad记录删除的点,deg记录点的度数
int vis[maxn];
int T, N, NN;
queue<int> q;
vector<int> vtt;
LL ans, must;
inline void init()
{
	no = 0;
	for(int i = 1; i <= NN; ++i)
	vis[i] = bad[i] = deg[i] = 0, head[i]=-1;
}
inline void add(int u, int v, LL w)
{
	edge[no].v = v; edge[no].w = w;
	edge[no].next = head[u]; head[u] = no++;
}
LL dfs(int cur, int father)
{
	vtt.push_back(cur);
	vis[cur] = 1;
	for(int k = head[cur], kk; k != -1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(v == father) continue;
		if(bad[v] || vis[v]) continue;
		vis[v] = 1; vtt.push_back(v);
		for(kk = head[v]; kk != -1; kk = edge[kk].next)
		if(!bad[edge[kk].v] && edge[kk].v != cur) break;
		return dfs(edge[kk].v, v)*edge[k].w%mod;
	}
	return 1;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d", &N);
		NN = N<<1; init();
		for(int i = 1; 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 = 1;	//所有必选边造成的权重
		for(int i = 1; i <= N; ++i)
		if(deg[N+i] == 1) q.push(N+i);
		while(!q.empty())
		{
			int u = q.front(); q.pop();
			bad[u] = 1;
			for(int k = head[u]; k != -1; k = edge[k].next)
			{
				int v = edge[k].v;
				if(bad[v]) continue;
				must = must*edge[k].w%mod;
				bad[v] = 1;
				for(int kk = head[v]; kk != -1; kk = edge[kk].next)
				{
					if(bad[edge[kk].v]) continue;
					if(--deg[edge[kk].v] == 1)
					q.push(edge[kk].v);
				}
			}
		}
		ans = must;
		for(int i = 1; i <= N; ++i)
		{
			//确定左部顶点的一条边便确定了整个连通块的所有边
			if(vis[i] || bad[i]) continue;
			LL ans1 = 0;
			for(int k = head[i], kk; k != -1; k = edge[k].next)
			{
				int v = edge[k].v;
				vtt.clear();
				vis[v] = 1;
				for(kk = head[v]; kk != -1; 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;
				vis[v] = 0;
				for(int j = 0; j < vtt.size(); ++j)
				vis[vtt[j]] = 0;
				//清空当前连通块的标记,操作另一条边
				vtt.push_back(v);
			}
			for(int j = 0; j < vtt.size(); ++j)
			vis[vtt[j]] = 1;
			ans = ans*ans1%mod;
		}
		printf("%lld\n", ans);
	}
	return 0;
}


继续加油~

相关文章:

  • 我的Java开发学习之旅------Java经典排序算法之插入排序
  • POJ-3352 Road Construction(边双连通分量+缩点)
  • 445port入侵详细解释
  • UVALive-5013 Similarity(二分图最大权匹配)
  • Cisco ASA-ASA 8.2-L2L ***
  • HDU-3440 House Man(差分约束系统)
  • 怎么安装docker registry
  • HDU-3666 THE MATRIX PROBLEM(差分约束系统判断存在与否+特殊剪枝)
  • Thinkphp学习04
  • HDU-4315 Climbing the Hill(阶梯博弈变形)
  • HDU-5724 Chess(SG函数+状压)
  • Randy Shoup与Andrew Phillips对微服务方面问题的解答
  • HDU-4109 Instrction Arrangement(差分约束系统+增加源点技巧)
  • WiFi覆盖下的生活 享受便利的同时 别忘记了安全
  • HDU-6103 Kirinriki - 2017 Multi-University Training Contest - Team 6(尺取)
  • ----------
  • 【EOS】Cleos基础
  • codis proxy处理流程
  • EOS是什么
  • idea + plantuml 画流程图
  • Java,console输出实时的转向GUI textbox
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript HTML DOM
  • Laravel 实践之路: 数据库迁移与数据填充
  • Redis学习笔记 - pipline(流水线、管道)
  • Sublime Text 2/3 绑定Eclipse快捷键
  • Tornado学习笔记(1)
  • 初识MongoDB分片
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 反思总结然后整装待发
  • 工程优化暨babel升级小记
  • 检测对象或数组
  • 坑!为什么View.startAnimation不起作用?
  • 排序算法之--选择排序
  • 如何进阶一名有竞争力的程序员?
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 走向全栈之MongoDB的使用
  • 最近的计划
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #Z0458. 树的中心2
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (层次遍历)104. 二叉树的最大深度
  • (六)激光线扫描-三维重建
  • (三)elasticsearch 源码之启动流程分析
  • (四)Android布局类型(线性布局LinearLayout)
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .form文件_一篇文章学会文件上传
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET 设计模式初探
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明