首页 > 其他分享 >AGC059B 题解

AGC059B 题解

时间:2024-08-03 11:07:08浏览次数:10  
标签:连边 cnt 颜色 int 题解 -- second AGC059B

对于一种构造,考虑怎么表示。

可以把相邻不同颜色建图连边。

注意到答案不可能小于 \(n-1\),否则图不联通,显然不可能。

考虑什么情况下是 \(n-1\)。图是一棵树。

考虑怎么构造出一棵树。

因为一种颜色出现次数大于等于这个点的度数,可以考虑可以确定叶子。

把剩余度数最小的往最大的连边,如果出现两个剩余度数为 1 的连边,说明不可能是树。否则是树。

怎么通过树构造原来的颜色序列?

最短颜色序列是 abacdcec,如果没用完某种颜色,可以往同种颜色后面一直添加,例如变成 abacccccdcec。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 2e5 + 5;
int a[N], cnt[N], n;
vector<pair<int, int>> e[N];

void dfs(int x)
{
    for(auto [i, j] : e[x])
    {
        for(int k = 1; k <= j; k ++) cout << i << " ";
        dfs(i);
        cout << x << " ";
    }
}

void solve()
{
    cin >> n;
    for(int i = 1; i <= n; i ++) cnt[i] = 0, e[i].clear();
    for(int i = 1; i <= n; i ++)
    {
        int x; cin >> x;
        a[i] = x;
        cnt[x] ++;
    }
    set<pair<int, int>> s;
    int fs;
    for(int i = 1; i <= n; i ++)
        if(cnt[i]) s.insert({cnt[i], i}), fs = i;
    int cc = s.size();
    while(s.size() > 1)
    {
        int a = s.begin()->second, b = s.rbegin()->second;
        if(fs == a) fs = b;
        e[b].push_back({a, cnt[a]});
        cc --;
        s.erase({cnt[a], a}); cnt[a] --;
        s.erase({cnt[b], b}); cnt[b] --;
        if(cnt[b]) s.insert({cnt[b], b});
    }
    if(cc != 1)
    {
        sort(a + 1, a + n + 1);
        for(int i = 1; i <= n; i ++) cout << a[i] << " ";
    }
    else if(s.empty())
    {
        dfs(fs);
    }
    else
    {
        for(int i = 0; i < s.begin()->first; i ++) cout << s.begin()->second << " ";
        dfs(s.begin()->second);
    }
    cout << "\n";
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    int t;cin >> t;while(t --) solve();

    return 0;
}

标签:连边,cnt,颜色,int,题解,--,second,AGC059B
From: https://www.cnblogs.com/adam01/p/18340193

相关文章

  • AGC056A 题解
    首先考虑\(n\equiv0\pmod3\)的情况。非常简单,然后考虑\(n\equiv1\pmod3\)的情况。只要把多出来的第一列第一行填满就行了。还要比原来情况多一个连通块。然后考虑\(n\equiv2\pmod3\)的情况。手玩一下,再往左上角添一点东西就行了。#include<bits/stdc++.h>us......
  • AGC044B 题解
    考虑每次更新就跑一遍bfs。\(O(n^4)\),复杂度不对?但是注意到\(dis\)的最大值也就是\(n\),每次更新\(dis\)至少减一。所以最大值最多被更新\(n\)次,一共更新\(O(n^3)\)次,复杂度是对的。直接暴力。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;......
  • ABC267F 题解
    注意到,对于一棵树\(T\)的任一直径\(a-b\),对于任意一点\(u\),离\(u\)最远的点一定是\(a\)或\(b\)。考虑反证:如图,如果存在点\(c\)使得\(dis(u,c)>\max(dis(u,a),dis(u,b))\)。如图,\(a-b\)为直径,\(d2>d1\)。因为有\(d4>d3+d2\),所以有\(d2+d3+d4>2d2+2d3>d1+d2\),所以......
  • ABC266F 题解
    输入的图是一颗基环树。对于\(x,y\),如果把环上的边去掉,得到的森林里\(x,y\)仍然在同一颗树内,那么显然只有一条路。否则一定要经过环,有两条路。于是dfs或着拓扑排序找环即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=2e5+......
  • 2024集训8.2模拟赛题解
    考试历程8:30开始考试8:40快速浏览了T1并想了一下,是一道质数的题目,准备打表,打到一半的时候发现空间复杂度会爆,于是改打质数筛暴力了9:30打完T1开始看T2刚开始没思路,先看了T3,跟着样例打了一点,估计可以拿点分吧9:50打完了T3会看T2发现了一点规律(后来知道是错的)跟着思路写了一......
  • gym105167E Erdős-Ginzburg-Ziv 题解
    题意:给\(p\)和\(p-1\)个边权,要用这些边权构造树,每个点编号\(0\simp-1\),使得每个点\(u\)到\(0\)的距离\(\bmod\p=u\),无解输出-1,保证\(p\)是质数、\(p\le10^6\)、边权\(\in[1..p-1]\).Solution考虑加边的过程,树最开始只有根节点0,然后通过加边不断地引入新的点......
  • 优秀的树 - 题解(数学)
    优秀的树时间限制:C/C++2000MS,其他语言4000MS内存限制:C/C++256MB,其他语言512MB描述给定一棵树,其所有边权重均为\(1\),定义\(f(u)=Σ_vdis(u,v)\),v表示树上的所有结点,\(dis(u,v)\)表示结点\(u\)和\(v\)的简单路径的长度。一棵树被称为“优秀”,当且仅当存在两个......
  • 【题解】走路
    I题意简述从原点出发,一步只能向右走、向上走或向左走。恰好走\(N\)步且不经过已走的点共有多少种走法?多组数据,每行输入一个数\(N\)。对于每一组测试数据,每行输出一个数,答案对\(12345\)取模。对于100%的数据,保证\(1\leqN\leq1000\)。时间限制\(1\text{s}\),空......
  • 树(tree) - 题解(带权并查集)
    树(tree)时间限制:C/C++2000MS,其他语言4000MS内存限制:C/C++256MB,其他语言512MB描述给定一个\(n\)个结点,\(n−1\)条边的有根树。第\(i\)条边可以用(\(a_i,b_i\))来描述,它表示连接结点\(a_i\)和结点\(b_i\)的一条边,其中结点\(a_i\)是结点\(b_i\)的父节点。......
  • Luogu P5005 中国象棋 - 摆上马 / Luogu P8756 国际象棋 题解 [ 蓝 ] [ 状压 dp ] [
    国际象棋:模板棋盘状压。摆上马:需要点思维的棋盘状压,相比上一道题加了“蹩马脚”的设定。Easy_version:国际象棋概述一下此类棋盘问题的思路:用二进制数表示出棋盘上某一行的状态。用位运算预处理出合法的单行状态,以及需要用到的一些东西。用位运算判断前一行或者前几行能否......