Codeforces Round #819 (Div. 1 + Div. 2) D. Edge Split

题意

You are given a connected, undirected and unweighted graph with n vertices and m edges. Notice the limit on the number of edges: m≤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 c1. Similarly, consider only the blue edges and count the number of connected components in the graph. Let this value be c2.
Find an assignment of colors to the edges such that the quantity c1+c2 is minimised.
给你一个连通无重边无向图,你需要将所有的边染色(蓝色和红色),使得只看红色边的连通分量个数 c 1 c_1 c1和只看蓝色边的连通分量个数 c 2 c_2 c2的和最小,即最小化 c 1 + c 2 c_1+c_2 c1+c2,给出染色方案。
题目链接

思路

我们肯定不希望某个颜色所形成的图中有环,因为有环相当于损失了一条边的作用。
首先我们可以将其中某一颗生成树染成红色,如果剩下的边只有0条或者1条或者2条,那么都不会构成环,已经得到答案。
如果剩下的边为3条,且构成环,那么随便选一条边 e e e染成红色,此时破环了蓝色的环,但此时红色成环,我们可以从 e e e的任意一个顶点 u u u出发,将从 u u u的边(除了 e e e)染成蓝色即可。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <cmath>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 200005;

struct edge
{
    int u, v;
}e[N];
int fa[N];
int ans[N];
int getf(int x)
{
    return x == fa[x] ? x : fa[x] = getf(fa[x]);
}

int main()
{
    int _; scanf("%d", &_);
    while (_ --)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i ++ )
            ans[i] = 0, scanf("%d%d", &e[i].u, &e[i].v);
        vector<int> E;
        for (int i = 1; i <= n; i ++ )
            fa[i] = i;
        
        for (int i = 1; i <= m; i ++ )
        {
            int u = getf(e[i].u), v = getf(e[i].v);
            if (u != v)
            {
                fa[u] = v;
                ans[i] = 1;
            }
            else E.push_back(i);
        }

        if (E.size() == 3)
        {
            set<int> v;
            for (int i = 0; i < E.size(); i ++ )
                v.insert(e[E[i]].u), v.insert(e[E[i]].v);
            if (v.size() == 3)
            {
                ans[E[0]] = 1;
                int vertex = e[E[0]].u;
                for (int i = 1; i <= m; i ++ )
                {
                    if (i == E[0]) continue;
                    if (e[i].u == vertex || e[i].v == vertex)
                        ans[i] = 0;
                }
            }
        }

        for (int i = 1; i <= m; i ++ )
            printf("%d", ans[i]);
        puts("");

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值