POJ 3723 Conscription【最小生成树】
2016-02-11 11:08
363 查看
题意:
征用一些男生和女生,每个应都要给10000元,但是如果某个男生和女生之间有关系,则给的钱数为10000减去相应的亲密度,征集一个士兵时一次关系只能使用一次。分析:
kruskal求最小生成树,注意男生和女生用偏移量处理。代码:
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; struct edge{int u, v, w;}; const int maxn = 20050, maxm = 50005; edge e[maxm]; int n, m ,R; int pa[maxn], _rank[maxn]; bool cmp(const edge &e1,const edge &e2) { return e1.w<e2.w; } int _find(int a) { if(a == pa[a]) return a; else return pa[a] = _find(pa[a]); } void unite(int a, int b) { int ra = _find(a), rb = _find(b); if(_rank[ra] < _rank[b]) pa[ra] = rb; else{ pa[rb] = ra; if(_rank[ra] == _rank[rb]) _rank[ra]++; } return; } int same(int a, int b) { return _find(a) == _find(b); } int kruskal(int r) { sort(e, e+r, cmp); for(int i = 0; i < n+m; i++){ pa[i] = i; } int res = 0; for(int i = 0; i < r; i++){ if(!same(e[i].u,e[i].v)){ unite(e[i].u, e[i].v); res += e[i].w; } } return res; } int main (void) { int c;scanf("%d",&c); while(c--){ fill(_rank, _rank + n + m, 1); scanf("%d%d%d",&n,&m,&R); int x, y, r; for(int i = 0; i < R;i++){ scanf("%d%d%d",&x, &y, &r); e[i] = (edge){x, y + n, -r}; } printf("%d\n",10000*(n+m) + kruskal(R)); } }
相关文章推荐
- Light OJ 1095 Arrange the Numbers (容斥)
- IT技术团队行而有效的管理之道
- LeetCode 104. Maximum Depth of Binary Tree
- poj 2750 Potted Flower(线段树+动态规划)
- 变频器直流母线电路示意图(转载)
- 7.屏幕适配
- 母线的种类与作用是什么(转)
- 信息安全----openssl
- 编写程序将2000年以内的平年闰年分开并分别计算个数
- 分布式事务的管理--atomikos
- 数的子结构
- 数组指针面试题
- ubuntu 下安装 QQ
- 线性方程组解法
- Unity-官方教程:我如何制作一个天空盒?
- opengl与dx
- 【NOI97】最优乘车
- The Java™ Tutorials — Concurrency :Interrupts 中断
- Mac OS的版本
- UVa 133 The Dole Queue