码迷,mamicode.com
首页 > 其他好文 > 详细

HDU6349-三原色图 Kruskal求最小生成树

时间:2018-08-10 21:30:44      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:信息   数据   bsp   ini   cep   node   string   return   sum   

三原色图

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 353    Accepted Submission(s): 134


Problem Description
度度熊有一张 n 个点 m 条边的无向图,所有点按照 1,2,?,n 标号,每条边有一个正整数权值以及一种色光三原色红、绿、蓝之一的颜色。

现在度度熊想选出恰好 k 条边,满足只用这 k 条边之中的红色边和绿色边就能使 n 个点之间两两连通,或者只用这 k 条边之中的蓝色边和绿色边就能使 n个点之间两两连通,这里两个点连通是指从一个点出发沿着边可以走到另一个点。

对于每个 k=1,2,?,m,你都需要帮度度熊计算选出恰好 k 条满足条件的边的权值之和的最小值。
 
Input
第一行包含一个正整数 T,表示有 T 组测试数据。

接下来依次描述 T 组测试数据。对于每组测试数据:

第一行包含两个整数 n 和 m,表示图的点数和边数。

接下来 m 行,每行包含三个整数 a,b,w 和一个字符 c,表示有一条连接点 a 与点 b 的权值为 w、颜色为 c 的无向边。

保证 1T1001n,m1001a,bn1w1000c{R,G,B},这里 R,G,B 分别表示红色、绿色和蓝色。
 

 

Output
对于每组测试数据,先输出一行信息 "Case #x:"(不含引号),其中 x 表示这是第 x 组测试数据,接下来 m 行,每行包含一个整数,第 i 行的整数表示选出恰好 i 条满足条件的边的权值之和的最小值,如果不存在合法方案,输出 ?1,行末不要有多余空格。
 
Sample Input
1
5 8
1 5 1 R
2 1 2 R
5 4 5 R
4 5 3 G
1 3 3 G
4 3 5 G
5 4 1 B
1 2 2 B
 
Sample Output
Case #1:
-1
-1
-1
9
10
12
17
22
 
思路:思路很简单,就是Kruskal求最小生成树。注意细节,当k>n-1时,边权和不再受颜色限制,只要是没用过的边都可以加进去
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define maxn 109
#define inf 0x3f3f3f3f
using namespace std;

int par[maxn], ranks[maxn];
void init_bcj(int n) {
	for (int i = 0; i <= n; i++) {
		par[i] = i;
		ranks[i] = 0;
	}
}
int find_bcj(int x) {
	if (par[x] == x) return x;
	else {
		return par[x] = find_bcj(par[x]);
	}
}
bool unite(int x, int y) {
	x = find_bcj(x);
	y = find_bcj(y);
	if (x == y) return 0;
	if (ranks[x] < ranks[y]) {
		par[x] = y;
	}
	else {
		par[y] = x;
		if (ranks[x] == ranks[y]) ranks[x]++;
	}
	return 1;
}
bool issame_bcj(int x, int y) {
	return find_bcj(x) == find_bcj(y);
}

int t, n, m;
int ans[maxn];
struct node_edge
{
	int u, v, w;
	char c;
}e[maxn];
bool cmp(const node_edge &a, const node_edge &b) {
	return a.w < b.w;
}
struct que
{
	int a[maxn];
	int count = 0;
};
void Kruskal(char fb) {
	init_bcj(n);
	que q;
	int sum = 0,anst;
	for (int i = 1; i <= m; i++) {
		if (e[i].c != fb) {
			if (!unite(e[i].u, e[i].v)) {
				q.a[q.count] = e[i].w; q.count++;
			}
			else sum += e[i].w;
		}
		else {
			q.a[q.count] = e[i].w; q.count++;
		}
	}
	anst = m - q.count;
	if (anst < n - 1) return;
	ans[anst] = min(sum,ans[anst]);
	for (int i = 0; i < q.count; i++) {
		anst++;
		sum += q.a[i];
		ans[anst] = min(ans[anst], sum);
	}
}

int main() {
	fio;
	cin >> t;
	for (int i = 1; i <= t; i++) {
		memset(ans, inf, sizeof ans);
		cin >> n >> m;
		for (int i = 1; i <= m; i++) {
			cin >> e[i].u >> e[i].v >> e[i].w >> e[i].c;
		}
		sort(e + 1, e + 1 + m, cmp);
		Kruskal(‘B‘);
		Kruskal(‘R‘);
		cout << "Case #"<<i<<":\n";
		for (int i = 1; i <= m; i++) {
			if (ans[i] == inf) cout << "-1" << endl;
			else cout << ans[i] << endl;
		}
	}
	return 0;
}

  

HDU6349-三原色图 Kruskal求最小生成树

标签:信息   数据   bsp   ini   cep   node   string   return   sum   

原文地址:https://www.cnblogs.com/the-way-of-cas/p/9457060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!