bzoj 4883(带环外向树森林)
来源:互联网 发布:代办软件著作权 编辑:程序博客网 时间:2024/06/04 19:27
题意:在一个n * m的棋盘上要放置若干个守卫。对于n行来说,每行必须恰好放置一个横向守卫;同理对于m列来说,每列必须恰好放置一个纵向守卫。每个位置放置守卫的代价是不一样的,且每个位置最多只能放置一个守卫,一个守卫不能同时兼顾行列的防御。请计算控制整个棋盘的最小代价。n * m<=100000
思路:很容易想到费用流,把(i,j)这个点看作是i和j两个点之间有一条费用为w[i][j]的边,进来总的流量为n+m,出去总的流量为n+m。然后其实,等价于,用n+m条边控制n+m个点的最小费用,就是这么个类kruskal的算法了。外向树上加一个环。
#include <bits/stdc++.h>using namespace std;const int maxn = 100000 + 5;struct Edge{ int u, v, cost; bool operator < (const Edge &other)const { return cost < other.cost; }}edges[maxn];int loop[maxn], fa[maxn];int uf_find(int x){return x == fa[x] ? x : fa[x] = uf_find(fa[x]);}long long kruskal(int vs, int es){ for(int i = 1; i < vs; i++) fa[i] = i; sort(edges, edges + es); long long ans = 0; for(int i = 0; i < es; i++) { Edge e = edges[i]; int fx = uf_find(e.u), fy = uf_find(e.v); if(loop[fx] && loop[fy]) continue; if(fx != fy) { fa[fx] = fy; loop[fy] |= loop[fx]; } else loop[fx] = 1; ans += e.cost; } return ans;}int main(){ int n, m, es = 0; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { int x; scanf("%d", &x); edges[es++] = {i, j + n, x}; } } printf("%lld\n", kruskal(n + m, es)); return 0;}
阅读全文
0 0
- bzoj 4883(带环外向树森林)
- bzoj-2878(外向树DP)
- BZOJ1040环加外向树森林上的动态规划
- BZOJ 3123 森林 主席树启发式合并
- BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)
- [基环外向树+树形DP]BZOJ 1040—— [ZJOI2008]骑士
- bzoj 3123: [Sdoi2013]森林 (主席树+启发式合并+并查集)
- bzoj-3669 魔法森林
- bzoj-3123 森林
- bzoj 4573大森林
- bzoj 3669 魔法森林
- BZOJ 3123: [Sdoi2013]森林
- 2017WHU校赛OL Werewolf (基环外向树)
- BZOJ 3875 - SPFA处理带环的DP
- BZOJ 3123 [Sdoi2013]森林 主席树+启发式合并
- BZOJ 3123: [Sdoi2013]森林|主席树|启发式合并
- [主席树 启发式合并] BZOJ 3123 [Sdoi2013]森林
- 【BZOJ 3123】[Sdoi2013]森林 启发式合并主席树
- Java中JSON字符串与java对象的互换实例详解
- bzoj 4773 负环(floyd倍增)
- 【angular】浏览器低版本报错,Object.assign
- Spring通过AOP在Service层注入用户信息
- ubuntu 登录界面无限循环问题解决方法
- bzoj 4883(带环外向树森林)
- 第一次使用Git bush
- Hibernateo之一对一,多对一
- 日语Google输入法学习
- 从一个点到另一个点的非单调路径(直接给结果)
- bzoj 4884 [Lydsy2017年5月月赛]太空猫(简单dp)
- 工作容易,赚钱很难
- 字符串
- TensorFlow全新的数据读取方式:Dataset API入门教程(转)