CF 1726 D. Edge Split 图论 2000

2 篇文章 0 订阅

题意:有一张 n 个顶点,m条边的连通图,m ≤ n+2。每条边可以染成红色或蓝色,然后只考虑红色的边,计算出图里的连通分量数量为 c1,同样只考虑蓝色的边,计算出连通分量的数量为c2,求出最小的 c1 + c2。

思路:我们有一张红色的图和一张蓝色的图,当有图里面出现环时,那么就说明有一条边浪费了,因为即使环里少一条边,这张图的连通分量数是不变的,所以最小的c1 + c2 就是要让两种颜色的图都不出现环。题目保证了 m 条边能构成一张连通图,所以 m ≥ n - 1,我们可以先将能构成一张连通图的 n - 1条边染成同一种颜色,那么这 n - 1条边不会出现环,再将剩下的边染成另一种颜色,因为 m ≤ n+2,所以最多还有三条边,而三条边刚好有可能形成一个环。如果m = n + 2,我们就检查一下多出来的三条边会不会成环,如果会的话,那就把其中一条边染成连通图的那一种颜色,再把连通图中顶点含有这条边的顶点的边颜色修改,那么两张图就都不会成环。

代码:

#include<bits/stdc++.h>
#define pb push_back
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10, P = 1e9 + 7, mod = 998244353;
int f[N];
PII a[N];
int find(int x){
	if(x != f[x]) f[x] = find(f[x]);
	return f[x];
}
void solve() {
	int n, m;
	cin >> n >> m;
	string ans(m, '0');
	for(int i = 1; i <= n; i++) f[i] = i;
	set<int> se;
	PII b;
	for(int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		a[i] = {u, v};
		int x = find(u), y = find(v);
		if(x == y) ans[i] = '1', se.insert(u), se.insert(v), b = a[i];
		else f[x] = f[y];
	}
	if(se.size() == 3 && m == n + 2) {
		for(int i = 0; i < m; i++) 
			if(a[i] == b) {
				ans[i] = '0';
				for(int j = 0; j < m; j++) {
					if(i != j && (b.first == a[j].first || b.first == a[j].second)) 
						ans[j] = '1';
				}
			}
	}
	cout << ans << endl;
}                
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int tt = 1;
	cin >> tt;
	while(tt--) {
		solve();
	}
	return 0;
}

                                                                                                 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值