BZOJ4883 棋盘上的守卫 基环树、Kruskal
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4883
题意:给出一个$N \times M$的棋盘,每个格子有权值。你需要每一行选中一个格子,每一列也选中一个格子(一个格子不能同时被行选中和被列选中),求这些格子权值和的最小值,$2 \leq N,M \leq 10^5 , N \times M \leq 10^5$
考虑将行与列拆成点,格子的权值变为连接其对应行与列对应节点的边,我们的问题也就是需要找到一个边集,使得每一条边都在只匹配其端点中的一个的情况下匹配到每一个点,并且边权之和最小。考虑如何找“每一条边都在只匹配其端点中的一个的情况下匹配到每一个点”的边集。我们发现一棵有$N$个节点的树可以匹配$N - 1$个点,那么我们再在树上加一条边,构成基环树,就能够满足条件了。如果我们将边变为有向边,方向向其匹配的那个点,那么满足条件的基环树就是基环外向树。所以我们的目标就是找到这个图中的最小生成基环森林,使用类似$Kruskal$的方法可以实现。
具体的实现方式在并查集上有不同。我们维护某个集合中是否有环。如果某条边对应的两个端点在同一并查集中,如果没有环则设为有环并加上边权,否则无法合并;合并时两个有环的并查集无法合并,否则合并这两个集合,并且继承有无环的状态。
#include<bits/stdc++.h>
#define ll long long
#define MAXN 100010
using namespace std;
inline ll read(){
ll a = ;
char c = getchar();
while(!isdigit(c))
c = getchar();
while(isdigit(c)){
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return a;
}
struct Edge{
ll start , end , w;
}Ed[MAXN];
ll fa[MAXN] , N , M;
bool vis[MAXN];
bool cmp(Edge a , Edge b){
return a.w < b.w;
}
ll find(ll x){
return fa[x] == x ? x : (fa[x] = find(fa[x]));
}
int main(){
ll ans = ;
N = read();
M = read();
; i <= N ; i++)
; j <= M ; j++){
Ed[(i - ) * M + j].start = i;
Ed[(i - ) * M + j].end = j + N;
Ed[(i - ) * M + j].w = read();
}
sort(Ed + , Ed + N * M + , cmp);
; i <= N + M ; i++){
fa[i] = i;
vis[i] = ;
}
; i <= N * M ; i++){
ll p = find(Ed[i].start) , q = find(Ed[i].end);
if(p != q && !(vis[p] && vis[q])){
fa[q] = p;
ans += Ed[i].w;
vis[p] |= vis[q];
}
else
if(!vis[p]){
vis[p] = ;
ans += Ed[i].w;
}
}
cout << ans;
;
}
BZOJ4883 棋盘上的守卫 基环树、Kruskal的更多相关文章
- bzoj 4883 棋盘上的守卫 —— 基环树转化
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4883 首先,注意到每个点可横可竖,但花费一样: 所以考虑行列的交集,那么这个条件可以转化为行 ...
- BZOJ4883 棋盘上的守卫(环套树+最小生成树)
容易想到网络流之类的东西,虽然范围看起来不太可做,不过这提供了一种想法,即将行列分别看做点.那么我们需要找一种连n+m条边的方案,使得可以从每条边中选一个点以覆盖所有点.显然每个点至少要连一条边.于是 ...
- BZOJ 4883 棋盘上的守卫 解题报告
BZOJ4883 棋盘上的守卫 考虑费用流,但是数据范围太大 考虑 \(i\) 行 \(j\) 列如果被选择,那么要么给 \(i\) 行,要么给 \(j\) 列 把选择 \(i\) 行 \(j\) 列 ...
- [CF1027F]Session in BSU[最小基环树森林]
题意 有 \(n\) 门课程,每门课程可以选择在 \(a_i\) 或者 \(b_i\) 天参加考试,每天最多考一门,问最早什么时候考完所有课程. \(n\leq 10^6\). 分析 类似 [BZOJ ...
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]
题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...
- bzoj4883 [Lydsy1705月赛]棋盘上的守卫 最小生成基环树森林
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4883 题解 每一行和每一列都必须要被覆盖. 考虑对于每一行和每一列都建立一个点,一行和一列之间 ...
- 【BZOJ4883】 [Lydsy1705月赛]棋盘上的守卫(最小生成树,基环树)
传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里
- 【题解】BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林)
[题解]BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林) 神题 我的想法是,每行每列都要有匹配且一个点只能匹配一个,于是就把格点和每行每列建点出来做一个最小生成树,但是不 ...
- BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)
4883: [Lydsy1705月赛]棋盘上的守卫 Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 475 Solved: 259[Submit][St ...
随机推荐
- drupal7常用函数
1.获取当前启用的管理员主题名称: $admin_theme = variable_get('admin_theme');
- OSGI企业应用开发(十四)整合Spring、Mybatis、Spring MVC
作为一个企业级的Web应用,MVC框架是必不可少的.Spring MVC目前使用也比较广泛,本文就来介绍一下如何在OSGI应用中实现Spring.Mybatis.Spring MVC框架的整合,其中S ...
- 记录定时任务的一个错误:crontab 中使用"%"的问题
最近工作需要,需要定时执行命令文件,并且把执行的日志重定向输出到以日期命名的文件中,命令如下: /bin/bash /data/shell/merge.sh &>> /data/s ...
- 洗礼灵魂,修炼python(9)--灵性的字符串
python几大核心之——字符串 1.什么是字符串 其实前面说到数据类型时说过了,就是带有引号的参数,“”引号内的一切东西就是字符串,字符串又叫文本. 2.创建字符串的两种方式: 3.字符串的方法: ...
- sql server 转置 和实现随机分配和一串代码的含义拼在一行
1.sql server 转置很容易搜到方法,一般需要手动写转置的列项,如果多时会比较烦,下面试了省事的方法: --案例需求数据 ----方法一:if object_id('tempdb.dbo.#s ...
- Sqoop-1.4.7-部署与常见案例
该文章是基于 Hadoop2.7.6_01_部署 . Hive-1.2.1_01_安装部署 进行的 1. 前言 在一个完整的大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核 ...
- css设置文字不能选中状态
高版本浏览器的处理方式 -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-u ...
- SQL查询语句,怎样查询重复数据
SQL查询语句,怎样查询重复数据 2012-02-22 14:50神奇的马骁勇 | 浏览 0 次 有表A, 中有字段id, name, memo现在有很多id重复的数据,怎么把这些重复的都查出来?gr ...
- Python字符串操作之字符串分割与组合
12.字符串的分割和组合 12.1 str.split():字符串分割函数 通过指定分隔符对字符串进行切片,并返回分割后的字符串列表. 语法: str.split(s, num)[n] 参数说明: s ...
- HTTP 请求方法
一.HTTP中定义了以下几种请求方法: 1.GET:2.POST:3.PUT:4.DELETE; 5.HEAD:6.TRACE:7.OPTIONS: 二.各个方法介绍: 1.GET方法: 对这个资源的 ...