BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)
4883: [Lydsy1705月赛]棋盘上的守卫
Time Limit: 3 Sec Memory Limit: 256 MB
Submit: 475 Solved: 259
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 3 10 8
2 1 9 2
6 7 4 6
Sample Output
HINT
在(1,1),(2,2),(3,1)放置横向守卫,在(2,1),(1,2),(3,3),(2,4)放置纵向守卫。
思路:一眼看出最小费用流,zkw跑几发T了,然后学习了下正解:环套树森林。
我们把行到列加无向边,然后得到最小环套树森林就ok了。(N+M个点,N+M个环,说明有一个环。)
得到这个环套树森林后,我们来定向,即这个无向边指向行还是列。我们假设指向的方向代表守卫的方向。假设多条边有公共顶点,他们中最多一个点指向这个公共顶点。 那么如果我们知道了一个连通块的一个指向,那么连通块的其他所有边指向都可以推出,而且这里二分图,所以环是偶环,不会出现矛盾。 这也是为什么可以这么做,即得到是环套树森林一定能得到合理方案。
Kruscal求最小环套树森林:按照常规的Kruscal来做,只是多了一个tag标记,表示它是否有环,合并之前保证最多一个环。
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int fa[maxn],tag[maxn],tot; ll ans;
struct in{
int x,y,len;
in(){}
in(int xx,int yy,int LL):x(xx),y(yy),len(LL){}
bool friend operator <(in w,in v){return w.len<v.len; }
}s[maxn];
int find(int x){
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
int main()
{
int N,M,x; scanf("%d%d",&N,&M);
rep(i,,N)
rep(j,,M){
scanf("%d",&x);
s[++tot]=in(i,N+j,x);
}
sort(s+,s+tot+);
rep(i,,N+M) fa[i]=i;
rep(i,,tot){
int a=find(s[i].x),b=find(s[i].y);
if(tag[a]&&tag[b]) continue;
if(a==b) tag[a]=;
else fa[b]=a,tag[a]|=tag[b];
ans+=s[i].len;
}
printf("%lld\n",ans);
return ;
}
BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)的更多相关文章
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]
题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...
- 【题解】BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林)
[题解]BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林) 神题 我的想法是,每行每列都要有匹配且一个点只能匹配一个,于是就把格点和每行每列建点出来做一个最小生成树,但是不 ...
- 【bzoj4883】[Lydsy2017年5月月赛]棋盘上的守卫 最小环套树森林
题目描述 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置最多只能放置一个 ...
- bzoj4883 [Lydsy1705月赛]棋盘上的守卫 最小生成基环树森林
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4883 题解 每一行和每一列都必须要被覆盖. 考虑对于每一行和每一列都建立一个点,一行和一列之间 ...
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫(Kruskal)
对每行每列分别建一个点,问题转为选n+m条边,并给每条边选一个点覆盖,使每个点都被覆盖.也就是最小生成环套树森林. 用和Kruskal一样的方法,将边从小到大排序,若一条边被选入后连通块仍然是一个环套 ...
- BZOJ4886: [Lydsy1705月赛]叠塔游戏(环套树森林&贪心)
4886: [Lydsy1705月赛]叠塔游戏 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 198 Solved: 76[Submit][Stat ...
- BZOJ4883 棋盘上的守卫(环套树+最小生成树)
容易想到网络流之类的东西,虽然范围看起来不太可做,不过这提供了一种想法,即将行列分别看做点.那么我们需要找一种连n+m条边的方案,使得可以从每条边中选一个点以覆盖所有点.显然每个点至少要连一条边.于是 ...
- BZOJ 4883: [Lydsy1705月赛]棋盘上的守卫 最小生成树 + 建模
Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置 ...
- 【BZOJ4883】 [Lydsy1705月赛]棋盘上的守卫(最小生成树,基环树)
传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里
随机推荐
- grub的安装与配置-------引导redhat grub
1.安装 有两种方法: a.在联网的情况下,用新立德安装: apt-get install grub b.在没网的时候,特别是linux网卡驱动没有安装: 自己从http://packages.ubu ...
- Spring整合Mybatis 之分页插件使用
[分页插件项目中的正式代码一共有个5个Java文件,这5个文件的说明如下] Page<E>[必须]:分页参数类,该类继承ArrayList,虽然分页查询返回的结果实际类型是Page< ...
- 892. Surface Area of 3D Shapes
问题 NxN个格子中,用1x1x1的立方体堆叠,grid[i][j]表示坐标格上堆叠的立方体个数,求这个3D多边形的表面积. Input: [[1,2],[3,4]] Output: 34 思路 只要 ...
- numpy模块学习笔记
# encoding=utf-8 import numpy as np from numpy.linalg import * def main(): # 1.最基本的array lst = [[1, ...
- 【知识总结】Activiti工作流学习入门
1. 我理解的工作流: 在工作中慢慢接触的业务流程,就向流程控制语言一样,一步一步都对应的不同的业务,但整体串联起来就是一个完整的业务.而且实际工作中尤其是在企业内部系统的研发中,确实需要对应许多审批 ...
- postman--实现接口自动化测试
postman使用 开发中经常用postman来测试接口,一个简单的注册接口用postman测试: 接口正常工作只是最基本的要求,经常要评估接口性能,进行压力测试. postman进行简单压力测试 下 ...
- JavaWeb实现分页的四种方法
一.借助数组进行分页 原理:进行数据库查询操作时,获取到数据库中所有满足条件的记录,保存在应用的临时数组中,再通过List的subList方法,获取到满足条件的所有记录. 实现: 首先在dao层,创建 ...
- constructor-arg和property的区别
两者都是给bean注入属性,区别: constructor-arg:通过构造函数注入. property:通过setter对应的方法注入. 详情见:https://blog.csdn.net/u012 ...
- 20145325张梓靖 实验四 "Andoid开发基础"
20145325张梓靖 实验四 "Andoid开发基础" 实验内容 使用 Android Studio 设计"Hello" 设计过程 创建项目 选择.xml中的 ...
- 获取当前线程id
转:https://www.cnblogs.com/comsky/p/6020327.html 如果获得当前进程的Id用: Process[] processes = Process.GetProce ...