2021牛客寒假算法基础集训营1 C红与蓝(匹配问题)

题目链接:https://ac.nowcoder.com/acm/contest/9981/C

题解:度为1,则一定和直接相连的抱团组队,比如i-j,du[i]=1,那么i,j组队,j也必须和其他的断绝联系(断绝联系之后du[k]为1就加入)。

总之,如果满足,一定两两组队。且组队问题,思考方向:先从选择较少的开始匹配。

组好队之后直接dfs一下就好了。

代码:

#include <bits/stdc++.h>

#define ll long long
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define rep(i, a, n) for (ll i = a; i <= n; i++)
#define per(i, n, a) for (ll i = n; i >= a; i--)
#define dbg(x) cout << #x << "===" << x << endl
#define dbgg(l, r, x)                                \
    for (ll i = l; i <= r; i++) cout << x[i] << " "; \
    cout << "<<<" << #x << "\n"
//多动脑,少动笔
using namespace std;

template <class T>
void read(T &x) {
    T res = 0, f = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (isdigit(c)) res = (res << 3) + (res << 1) + c - '0', c = getchar();
    x = res * f;
}
void Printf(ll x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) Printf(x / 10);
    putchar(x % 10 + '0');
}
void print(ll x, char c) { Printf(x), putchar(c); }
const ll maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll inf = 1e9;

ll n, u, v, du[maxn], p[maxn];
char c[maxn];
set<ll> st[maxn];
vector<ll> g[maxn];
ll vis[maxn];
bool topo(){
    queue<ll> q;
    rep(i,1,n){
        if(du[i]==1) q.push(i),vis[i]=1;//,dbg(i);
    }
    ll cnt=0;
    while(!q.empty()){
        ll i=q.front();q.pop();
        // dbg(i);
        ll j=*st[i].begin();
        // dbg(j);
        vis[j]=1;
        st[i].erase(j);
        st[j].erase(i);
        p[i]=j,p[j]=i;
        cnt+=2;
        for(auto k:st[j]){
            du[k]--;
            st[k].erase(j);
            if(du[k]==1){
                ll tmp=*st[k].begin();
                if(vis[tmp]) continue;
                q.push(k),vis[k]=1;
            }
        }
    }
    if(cnt!=n) return false;
    // dbg(cnt);
    return true;
}
void dfs(ll x,ll fa){
    for(auto i:g[x]){
        if(i==fa) continue;
        if(p[i]==x) c[i]=c[x];
        else{
            if(c[x]=='R') c[i]='B';
            else c[i]='R';
        }
        dfs(i,x);
    }
}
int main() {
    // freopen("testdata.in","r",stdin);
    // freopen("testout.out","w",stdout);
    ll TT = 1;
    // read(TT);
    while (TT--) {
        read(n);
        bool f=true;
        rep(i, 1, n - 1) {
            read(u),read(v);
            du[u]++,du[v]++;
            st[u].insert(v),st[v].insert(u);
            g[u].pb(v),g[v].pb(u);
        }
        // rep(i,1,n){
            // cout<<">>>"<<i<<endl;
            // for(auto j:st[i]) print(j,' ');puts("");
        // }
        f=topo();
        if(!f) puts("-1");
        else{
            // dbgg(1,n,p);
            c[1]='R';
            dfs(1,-1);
            rep(i,1,n) putchar(c[i]);puts("");
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值