【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4883

【题目大意】

  在一个n*m的棋盘上要放置若干个守卫。
  对于n行来说,每行必须恰好放置一个横向守卫;同理对于m列来说,
  每列必须恰好放置一个纵向守卫。每个位置放置守卫的代价是不一样的,
  且每个位置最多只能放置一个守卫,一个守卫不能同时兼顾行列的防御。
  请计算控制整个棋盘的最小代价。

【题解】

  我们将每行和每列看成一个点,用每个格子上的点的权值作为边,
  这就构成了一个n+m个点的图。
  我们发现对于n个点的集合,为了满足题目中的要求,就至少要包含n条边。
  所以题目就转化成求图中的最小生成环套树森林。

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=200010;
LL ans;
int x,n,m,f[N],v[N];
struct E{int u,v,c;E(){}E(int u,int v,int c):u(u),v(v),c(c){};}e[N];
bool cmp(E x,E y){return x.c<y.c;}
int sf(int x){return x==f[x]?x:f[x]=sf(f[x]);}
int main(){
while(~scanf("%d%d",&n,&m)){
int cnt=ans=0;
for(int i=1;i<=n+m;i++)f[i]=i,v[i]=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
scanf("%d",&x);
e[++cnt]=E(i,j+n,x);
}sort(e+1,e+cnt+1,cmp);
for(int i=1;i<=cnt;i++){
int fx=sf(f[e[i].u]),fy=sf(f[e[i].v]);
if(v[fx]&&v[fy])continue;
if(fx!=fy)v[fy]|=v[fx],f[fx]=fy;else v[fx]=1;
ans+=e[i].c;
}printf("%lld\n",ans);
}return 0;
}

最新文章

  1. Oracle中生成随机数的函数(转载)
  2. 【云计算】docker前世今生
  3. apt-get命令详解
  4. [电子书] 《Android编程入门很简单》
  5. JAVA排序--[选择排序]
  6. iOS进阶学习-数据处理之文件读写
  7. 254. Factor Combinations
  8. css中bug记录
  9. 随机法解决TSP问题
  10. IDL 的读写
  11. jq交叉淡入淡出轮播图
  12. 软件工程第三次作业-结对作业NO.1
  13. zipline-benchmarks.py文件改写
  14. 【Chrome插件】去掉因使用jsonView插件的弹出窗口&quot;请停用以开发者模式运行的扩展程序&quot;
  15. XAML: 在 MVVM 模式中,关于绑定的几处技巧
  16. Trident的过滤操作
  17. 十六、springcloud(二)Eureka集群
  18. python全局解释器锁(GIL)
  19. spring冲刺第三天
  20. Javascript的执行过程详细研究

热门文章

  1. linux 3389连接工具Rdesktop
  2. vue中的图片加载与显示默认图片
  3. Vue组件-使用插槽分发内容
  4. Linux 入门记录:二、Linux 文件系统基本结构
  5. sicily 1059. Exocenter of a Trian
  6. 生命周期(vue的钩子函数)
  7. django开发项目实例3--用session是实现简单的登陆、验证登陆和注销功能
  8. linux命令(15):mount/umount命令
  9. LeetCode解题报告—— Word Search &amp; Subsets II &amp; Decode Ways
  10. QT中ui更改后不能更新的解决方法