[思维][找环]Edge Split Codeforces1726D

59 篇文章 0 订阅
48 篇文章 0 订阅

You are given a connected, undirected and unweighted graph with nn vertices and mm edges. Notice the limit on the number of edges: m≤n+2m≤n+2.

Let's say we color some of the edges red and the remaining edges blue. Now consider only the red edges and count the number of connected components in the graph. Let this value be c1c1. Similarly, consider only the blue edges and count the number of connected components in the graph. Let this value be c2c2.

Find an assignment of colors to the edges such that the quantity c1+c2c1+c2 is minimised.

Input

Each test contains multiple test cases. The first line contains a single integer tt (1≤t≤1051≤t≤105) — the number of test cases. Description of the test cases follows.

The first line of each test case contains two integers nn and mm (2≤n≤2⋅1052≤n≤2⋅105; n−1≤m≤min(n+2,n⋅(n−1)2)n−1≤m≤min(n+2,n⋅(n−1)2)) — the number of vertices and the number of edges respectively.

mm lines follow. The ii-th line contains two integers uiui and vivi (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi) denoting that the ii-th edge goes between vertices uiui and vivi. The input is guaranteed to have no multiple edges or self loops. The graph is also guaranteed to be connected.

It is guaranteed that the sum of nn over all test cases does not exceed 106106. It is guaranteed that the sum of mm over all test cases does not exceed 2⋅1062⋅106.

Output

For each test case, output a binary string of length mm. The ii-th character of the string should be 1 if the ii-th edge should be colored red, and 0 if it should be colored blue. If there are multiple ways to assign colors to edges that give the minimum answer, you may output any.

Example

input

4

5 7

1 2

2 3

3 4

4 5

5 1

1 3

3 5

4 4

1 2

2 3

1 4

3 4

6 7

1 2

1 3

3 4

4 5

1 4

5 6

6 2

2 1

1 2

output

0111010

1001

0001111

0

题意: 给出n个点m条边(m <= n+2),你可以对每条边进行染色,要么染蓝色要么染红色,c1表示只看红色边形成的连通块个数,c2表示只看蓝色边形成的连通块个数,求使c1+c2最小的染色方案。

分析: 让c1+c2最小意味着不管是红色图还是蓝色图,其中都不能出现环路,否则相当于浪费了一条边。另外c1+c2的最小值一定是2*n-m,这是因为在不浪费边的前提下,每次染色一定能够合并掉一个连通块,最多m条边所以最多合并掉m个连通块,还剩下2*n-m个。

这样问题就可以转化为如何选出一个无环的边集A,使得剩下的边集B仍然无环,比较容易想到构造出一棵树作为A,这样剩下的边数可能为0、1、2和3,只要剩下边数不为3,那它们一定不可能构成环,可以达到最优解,而对于剩下边数为3的情况,如果三边构不成三角形,那同样能得到最优解,如果三边构成了三角形,那就选择其中一条边e加入树A,树中多了一条边肯定会出现环,所以还需要在树A的环路中删除一条非e的边,这样最终树A和剩下边集B中均无回路,可以达到最优解。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#define pii pair<int, int>
using namespace std;

vector<pii> to[200005];
int u[200005], v[200005], ans[200005], fa[200005], num[200005], cir;
bool vis[200005];

int find(int x){
	if(x == fa[x]) return x;
	return fa[x] = find(fa[x]);
}

void dfs(int now, int pre, int s, int e){
	if(cir != -1) return;
	for(int i = 0; i < to[now].size(); i++){
		int id = to[now][i].second;
		int son = to[now][i].first;
		if(!ans[id]) continue;
		if(son == pre) continue;
		if(!vis[son]){
			vis[son] = true;
			dfs(son, now, s, e);
		}
		else{
			if(now == s && son == e) continue;
			cir = id;
		}
	}
}

signed main()
{
	int T;
	cin >> T;
	while(T--){
		int n, m;
		scanf("%d%d", &n, &m);
		for(int i = 1; i <= n; i++){
			num[i] = 0;
			vis[i] = false;
			fa[i] = i;
			to[i].clear();
		}
		for(int i = 1; i <= m; i++) ans[i] = 0;
		int cnt = 0;
		int e = 0;
		int id;
		for(int i = 1; i <= m; i++){
			scanf("%d%d", &u[i], &v[i]);
			to[u[i]].push_back(make_pair(v[i], i));
			to[v[i]].push_back(make_pair(u[i], i));
			if(find(u[i]) != find(v[i])){
				ans[i] = 1;
				fa[find(u[i])] = find(v[i]);
			}
			else{
				if(!num[u[i]]) cnt++;
				num[u[i]]++;
				if(!num[v[i]]) cnt++;
				num[v[i]]++;
				e++;
				id = i;
			}
		}
		if(cnt == 3 && e == cnt){
			ans[id] = 1;
			cir = -1;
			vis[u[id]] = true;
			vis[v[id]] = true;
			dfs(u[id], 0, u[id], v[id]);
			ans[cir] = 0;
		}
		for(int i = 1; i <= m; i++)
			printf("%d", ans[i]);
		puts("");
	}
	return 0;
}
/*
5 5
1 2 2 3 3 4 4 5 5 3
11000
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值