原题链接:http://codeforces.com/gym/100431/attachments/download/2421/20092010-winter-petrozavodsk-camp-andrew-stankevich-contest-37-asc-37-en.pdf

题意

给你一个n,让你构造一个环,使得相邻的节点的颜色不一样,问最多能使用多少颜色,并且输出染色方案。

题解

首先,我们来考察对于k个颜色,我们至少需要多少节点。每个点可以连接两个点,将边考虑为有向边,如果我们不浪费任何一条边,对于一个颜色,我们将它连到其余的一半的颜色,将另外一半的颜色连接到他,由于可能除不尽,所以要向上取整。这样,我们得到了一个简单的公式,对于偶数的颜色k,我们需要k*k/2的点,对于奇数的颜色k,我们需要k*(k-1)/2的点。

现在反过来思考,对于给定的节点数,我们至少需要多少颜色。如果刚刚够用,自然最好,如若不然,就寻找一个合适的k,然后采取在多于的节点随便染色的策略。但事实并非如此,因为题意要求是个环,那么我们如若在最后补颜色,那么就会拆开最后一条边,所以,如果给的n只比合适值多1,那么颜色数就要减一,这就是为什么4个点的答案是2而3个点的答案是3。

接下来,我们来考虑如何构造解。对于我们已经构建好的有向图,本质上是要遍历所有的边。那么只需要在最初弄好的颜色的有向图上跑一发欧拉回路。然后我们需要填充多于的节点,为了避免出现拆开唯一的颜色边,所以应当将一个重复的边拆开,再在里面插点。插点时需要满足题意的条件。

此题坑非常多,需要十分细致,最好手算一下前10的答案,然后比对一下输出。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#define MAX_N 1234
using namespace std; int gao[MAX_N];
int k;
struct edge
{
bool vis;
int to;
edge(int t)
:vis(),to(t){}
edge(){}
}; vector<edge> G[MAX_N];
int tot=,road[MAX_N];
bool flag=false;
int n; int st[MAX_N],all=; void dfs(int u) {
//cout<<u<<endl;
int i = gao[u];
while (i < G[u].size() && G[u][i].vis)i++;
if (i == G[u].size())return;
gao[u] = i + ;
G[u][i].vis = ;
st[all++] = G[u][i].to;
dfs(G[u][i].to);
} bool check(int u) {
//cout<<G[u][0].vis<<endl;
if (gao[u] == G[u].size())return false;
return true;
} void Fluery(int s) {
st[all++] = s;
while (all) {
int now = st[all - ];
if (check(now))dfs(now);
else {
//cout<<rHash(now)<<endl;
road[tot++] = now;
all--;
}
}
} bool vis[MAX_N][MAX_N];
int newRoad[MAX_N]; int main() {
freopen("achromatic.in","r",stdin);
freopen("achromatic.out","w",stdout);
scanf("%d", &n);
for (k = ; ; k++) {
int t;
if (k & )t = k * (k - ) / ;
else t = k * k / ;
if (t > n)break;
}
k--;
if ((k & ) && n == (k * (k - )) / + )k--;
printf("%d\n", k);
for (int i = ; i < k; i++)
for (int j = ; j <= k / ; j++) {
int u = i;
int v = (i + j) % k;
G[u].push_back(edge(v));
}
Fluery();
int pos = ;
for (int i = ; i < tot - ; i++) {
int u = i, v = (i + ) % (tot - );
if (vis[u][v]) {
pos = u;
break;
}
vis[u][v] = vis[v][u] = ;
}
int nt = ;
for (int i = pos + ; i < tot - ; i++)
newRoad[nt++] = road[i];
for (int i = ; i <= pos; i++)newRoad[nt++] = road[i];
for (int i = ; i < tot - ; i++)
printf("%d ", newRoad[i] + );
if (n == tot - ) { return ; }
if (n - (tot - ) == ) {
int j = ;
while (j == newRoad[tot - ] + || j == newRoad[] + ) {
j++;
if (j == k + )j = ;
}
printf("%d\n", j);
return ;
}
printf("%d ", newRoad[] + );
int p = newRoad[] + ;
for (int i = tot; i < n; i++) {
int j = ;
while (j == p || (i == n - && j == newRoad[] + )) {
j++;
if (j == k + )j = ;
}
printf("%d ", j);
p = j;
}
printf("\n");
return ;
}

Codeforces Gym 100431A Achromatic Number 欧拉回路的更多相关文章

  1. Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】

     2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...

  2. Codeforces Gym 101252D&&floyd判圈算法学习笔记

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

  3. Codeforces Gym 101190M Mole Tunnels - 费用流

    题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...

  4. Codeforces Gym 101623A - 动态规划

    题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...

  5. 【Codeforces Gym 100725K】Key Insertion

    Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...

  6. codeforces gym 100553I

    codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...

  7. CodeForces Gym 100213F Counterfeit Money

    CodeForces Gym题目页面传送门 有\(1\)个\(n1\times m1\)的字符矩阵\(a\)和\(1\)个\(n2\times m2\)的字符矩阵\(b\),求\(a,b\)的最大公共 ...

  8. Codeforces GYM 100876 J - Buying roads 题解

    Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...

  9. codeforces Gym 100187J J. Deck Shuffling dfs

    J. Deck Shuffling Time Limit: 2   Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...

随机推荐

  1. 多线程辅助类之CyclicBarrier(四)

    CyclicBarrier是一个线程辅助类,和<多线程辅助类之CountDownLatch(三)>功能类似,都可以实现一组线程的相互等待.要说不通点,那就是CyclicBarrier在释放 ...

  2. LeetCode(282) Peeking Iterator

    题目 Given an Iterator class interface with methods: next() and hasNext(), design and implement a Peek ...

  3. 异常 ndroid.view.InflateException: Binary XML file line #8: Error inflating class com.ouyang.test.MyView

    发现自定义view时出现ndroid.view.InflateException: Binary XML file line #8: Error inflating class com.ouyang. ...

  4. ORACLE 分区表 相关视图

    1. 显示当前用户可访问的所有分区表信息﹕ ALL_PART_TABLES 2. 显示当前用户所有分区表的信息﹕ USER_PART_TABLES 3. 显示表分区信息 显示数据库所有分区表的详细分区 ...

  5. day04_01 知识回顾、算术运算符

    ","和"+"的区别 除法运算,整除//,别名"地板除" 取余数 2**10 2的10次方 指数运算 指数运算符优先级要比乘法要高,所以先算 ...

  6. HTTP LVS

    1. Configure the director 2.

  7. 【转】简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候很容易看到下面这个例子: 1 void Start () { 2 StartCoroutine(Destroy()); 3 } 4 5 IEnumerator Destroy ...

  8. 读懂diff(转载)

    作者: 阮一峰 日期: 2012年8月29日 diff是Unix系统的一个很重要的工具程序. 它用来比较两个文本文件的差异,是代码版本管理的基石之一.你在命令行下,输入: $ diff <变动前 ...

  9. linux查找文件命令

    (2)find /etc -name httpd.conf #在/etc目录下文件httpd.conf

  10. Visual Code 自定义插件安装位置

    修改快速方式通过传入方式启动 ,示例: D:\installed_green_soft\VSCode\Code.exe --extensions-dir "D:\installed_gree ...