无向图最大权森林问题(POJ3723)
问题 最大 森林 无向
2023-06-13 09:14:16 时间
题目:http://poj.org/problem?id=3723
Conscription
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 24785 Accepted: 8280
Description
Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girl x and boy y have a relationship d and one of them has been collected, Windy can collect the other one with 10000-d RMB. Now given all the relationships between girls and boys, your assignment is to find the least amount of money Windy has to pay. Notice that only one relationship can be used when collecting one soldier.
Input
The first line of input is the number of test case.
The first line of each test case contains three integers, N, M and R.
Then R lines followed, each contains three integers xi, yi and di.
There is a blank line before each test case.
1 ≤ N, M ≤ 10000
0 ≤ R ≤ 50,000
0 ≤ xi < N
0 ≤ yi < M
0 < di < 10000
Output
For each test case output the answer in a single line.
Sample Input
2
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781
5 5 10
2 4 9820
3 2 6236
3 1 8864
2 4 8326
2 0 5156
2 0 1463
4 1 2439
0 4 4373
3 4 8889
2 4 3133
Sample Output
71071
54223
这题乍一看没想出该怎么做,看了书才明白。首先肯定是先建图啦!然后因为要求最小花费,而每个人的花费是10000-(已征募的人中和自己亲密度的最大值)。而亲密度是已经给出的,且亲密度越大,花费越少。
转换为最小生成树问题
只要我们把亲密度都取负数,再求最小生成树,就能得出最小的花费了。由于这个图不一定是连通的,我们实际上是对不同的连通分量求最小生成树。因此我们采用Kruskal算法求解最小生成树。
AC代码:
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
#define MAXN 10005
typedef long long ll;
struct edge
{
int from, to, cost;
} e[5 * MAXN];
bool cmp(const edge &a, const edge &b)
{
return a.cost < b.cost;
}
int fa[3*MAXN];
int height[3*MAXN];
int n, m, r;
//初始化并查集
void init_ufs(int sz)
{
for (int i = 0; i <= sz; ++i)
fa[i] = i;
memset(height, 0, sizeof(height));
}
int find_set(const int x)
{
if (fa[x] == x)
return x;
fa[x] = find_set(fa[x]);
return fa[x];
}
bool same(const int &a, const int &b)
{
return find_set(a) == find_set(b);
}
void unite(int a, int b)
{
a = find_set(a);
b = find_set(b);
if (a != b)
{
if (height[a] < height[b])
{
fa[a] = b;
}
else
{
fa[b] = a;
if (height[a] == height[b])
++height[a];
}
}
}
int kruskal()
{
sort(e, e + r, cmp);
init_ufs(n+m);
int ans = 0;
for (int i = 0; i < r; ++i)
{
if (!same(e[i].from, e[i].to))
{
//cout<<e[i].from<<" "<<e[i].to<<endl;
unite(e[i].from, e[i].to);
ans += e[i].cost;
}
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &n, &m, &r);
int xi, yi, di;
for (int i = 0; i < r; ++i)
{
scanf("%d%d%d", &xi, &yi, &di);
//e[i] = (edge){xi, yi + n, -di};
e[i].from = xi;
e[i].to = yi+n;
e[i].cost = -di;
}
printf("%lld\n", 10000ll * (m + n) + kruskal());
}
}
相关文章
- 考研竞赛每日一练 day 29 利用泰勒公式解决级数收敛性证明问题
- 二分图最大匹配问题(匈牙利算法)
- 怎样通过iisapp命令查找pid来解决IIS的cpu占用率过高问题
- 解决Oracle数据倾斜问题(oracle数据倾斜)
- 值解决MySQL ID最大值临界点问题(mysqlid最大)
- 遇到的问题Linux扩展分区:解决遇到的困难(linux扩展分区分区)
- 可穿戴心电图机加盟全球最大房颤筛查项目,解决临床数据缺失问题
- 解决 MSSQL 无法连接的问题(mssql无法连接)
- 智能投顾行业最大问题是什么?智能投顾是风口还是泡沫? | 对话
- SQL Server查询:如何处理锁表问题(sqlserver查询锁表)
- MySQL数据库的编码问题不指定编码引发的数据混乱与解决方法(mysql不指定编码)
- 不发消息Redis订阅长时间问题消息不再飞舞(redis订阅长时间)
- 如何解决无法安装Oracle10g的问题(oracle10g装不上)
- 美议员提议制裁荣耀 赵明回应:做好自己事情 问题可以解决
- TextArea控件的最大长度问题(jsjson)
- Jquery网页出现的乱码问题的三种解决方法
- javascript:void(0)的问题使用探讨