题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4883

首先,注意到每个点可横可竖,但花费一样;

所以考虑行列的交集,那么这个条件可以转化为行点和列点之间的边,边权就是花费;

如果行和列都按原图交点连了边,那么问题就转化成在有向图中,每个点(原图的行/列)都有且仅有1入度;

这个性质让我们联想到基环树,所以只需要构造一个基环树森林即可;

又要边权和最小,仿照 Kruskal,从小到大加边,对于连通块,看看是否已经有环即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=2e5+;
int n,m,ct,fa[xn];
ll ans;
bool v[xn];
struct N{int u,v,w;}ed[xn<<];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
int main()
{
n=rd(); m=rd();
for(int i=;i<=n;i++)
for(int j=,z;j<=m;j++)
{
z=rd();
ed[++ct].u=i; ed[ct].v=j+n; ed[ct].w=z;
}
for(int i=;i<=n+m;i++)fa[i]=i;
sort(ed+,ed+ct+,cmp);
for(int i=;i<=ct;i++)
{
int x=find(ed[i].u),y=find(ed[i].v),w=ed[i].w;
if(x==y)
{
if(v[x])continue;
else ans+=w,v[x]=;
}
else
{
if(v[x]&&v[y])continue;
else if(v[x]||v[y])ans+=w,fa[x]=y,v[y]=;
else ans+=w,fa[x]=y;
}
}
printf("%lld\n",ans);
return ;
}

bzoj 4883 棋盘上的守卫 —— 基环树转化的更多相关文章

  1. BZOJ 4883 棋盘上的守卫 解题报告

    BZOJ4883 棋盘上的守卫 考虑费用流,但是数据范围太大 考虑 \(i\) 行 \(j\) 列如果被选择,那么要么给 \(i\) 行,要么给 \(j\) 列 把选择 \(i\) 行 \(j\) 列 ...

  2. BZOJ4883 棋盘上的守卫 基环树、Kruskal

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4883 题意:给出一个$N \times M$的棋盘,每个格子有权值.你需要每一行选中一 ...

  3. BZOJ 1040: [ZJOI2008]骑士(基环树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题意: 思路: 这是基环树,因为每个人只会有一个厌恶的人,所以每个节点只会有一个父亲节点,但是 ...

  4. BZOJ 1791: [IOI2008]Island 岛屿 - 基环树

    传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...

  5. bzoj 1040: [ZJOI2008]骑士【基环树+树形dp】

    没考虑可以连着两个不选--直接染色了 实际上是基环森林,对于每棵基环树,dfs找出一个环边,然后断掉这条边,分别对这条边的两端点做一边treedp,取max加进答案里 treedp是设f[u]为选u点 ...

  6. BZOJ - 3242 :快餐店 (基环树DP) 最小化半径

    题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近. 思路:为了保留整数,我们求最小直径,最后去除2.  直径来源于两部分: 1,在外向树中: 那么就是树的直接,一棵 ...

  7. BZOJ 4883: [Lydsy1705月赛]棋盘上的守卫 最小生成树 + 建模

    Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置 ...

  8. 【BZOJ4883】 [Lydsy1705月赛]棋盘上的守卫(最小生成树,基环树)

    传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里

  9. [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]

    题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...

随机推荐

  1. VM搭建hadoop分布式集群

    1.  安装VMware Workstation Pro 2.安装Ubuntu-16.04 3.以下全程使用sudo –s 切换root权限 4.更新deb软件包列表:apt-get update 5 ...

  2. linux 负载各项查看命令

    free -h top -c 查看使用情况 sar -r/s/b 查看IO状态 iostat -x 1 10 查看服务器的状态 vmstat 查看内存使用率最后的前10个进程 ps -aux |sor ...

  3. (十)python3 生成器

    生成器(generator):在 Python 中,不必创建完整的 list,从而节省大量的空间.一边循环一边计算的机制. 创建一个 generator,有很多种方法.第一种方法很简单,只要把一个列表 ...

  4. day21 04 三级菜单

    day21 04 三级菜单 1.使用递归调用的方法 整体代码类型比较简单如下: menu={'北京':{'海淀':{'a':{},'h':{},'c':{}},'昌平':{'沙河':{},'天通苑': ...

  5. js 小练习

    js 学习之路代码记录 js 加载时间线 1.创建Document对象,开始解析web页面.解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中.这个阶段document.r ...

  6. Mac 共享无线网络

    dock栏启动『设置』进入下一步.   进入设置后,点击『共享』进入下一步.   进入共享后 1.选择左边框中『互联网共享』,就会看到截图右边的样子 2.『共享以下来源链接』一项选择『以太网』(默认应 ...

  7. HASH的应用(负数下标用偏移量解决)

    Input 每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个处于区间[-500000,500000]的整数. Output 对每组测试数据按从大到小的 ...

  8. chrome webstore

    chrome webstore https://chrome.google.com/webstore/detail/set-character-encoding/bpojelgakakmcfmjfil ...

  9. Spring boot 搭配 JPA 生成表注释 和 字段注释

    原文地址:https://blog.csdn.net/qq_39996837/article/details/84717748 由于在数据库表反向生成过程中呢,需要通过jpa自动生成表,并且这个表必须 ...

  10. 【HDOJ5714】拍照(线性扫描)

    题意:小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行.小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中. 小明位于河的边上,并且可以在河边 ...