\(\mathcal{Decription}\)

  Link.

  这是一道通信题。

  给定一个 \(n\) 个点 \(m\) 条边的连通无向图与两个限制 \(A,B\)。

  程序 Anthony 需要用 \(0\sim A-1\) 共 \(A\) 中颜色为无向图的每条边染色。

  程序 Catherine 需要帮助一只猫行走:已知猫所在结点邻接每种颜色的边的数量,你需要告诉猫走哪种颜色的边(但不能让它走特定某条),并保证猫从起点 \(s\) 到 \(0\) 所走的距离不超过两点最短距离 \(+B\)。

  \(n,m\le2\times10^4\),\(A,B\) 满足 \(A\ge 3,B\ge0\) 或 \(A\ge 2,B\ge6\) 的一种,满足后者时,\(m=n-1\)。

\(\mathcal{Solution}\)

  就**离谱好吗 qwq!

\(\mathcal{Anthony}\)

  嘛……不难看出两种情况是割裂的,分类讨论咯。

\(\mathcal{Part~1}\)

  \(A=3,B=0\),相当于要求我们必须走最短路

  考虑从 \(0\) 出发,用 BFS 将图分层,设结点到 \(0\) 的距离为 \(dist_i\) 的点都在第 \(dist_i\) 层。注意猫是要从终点向回走,所以我们应当把连接上一层的边和连接同层连接下一层的边区分开来。一种方法是令 \(color(u,v)=\min\{dist_u,dist_v\}\bmod3\),则一个点的邻接边颜色不超过两种,判一判那条边是向上层的即可。

\(\mathcal{Part~1-Code}\)

namespace Task1 {

bool vis[MAXN + 5];

inline vecint main ( vecint U, vecint V ) {
std::queue<int> que;
que.push ( 0 ), vis[0] = true;
while ( ! que.empty () ) {
int u = que.front (); que.pop ();
for ( pii v: graph[u] ) if ( ! vis[v.first] ) {
dist[v.first] = dist[u] + 1;
que.push ( v.first ), vis[v.first] = true;
}
}
vecint ret ( m );
for ( int i = 0; i < m; ++ i ) ret[i] = std::min ( dist[U[i]], dist[V[i]] ) % 3;
return ret;
} } // namespace RybyA::Task1.

\(\mathcal{Part~2}\)

  \(A=2,B=6\),一棵树。如果以 \(0\) 为根,无脑往上走就好啦。问题在于如何将一个结点的父亲与儿子们区分开来。

  若 \(d_u>2\),即 \(u\) 有多于一个儿子,那么令向儿子们的颜色相同,向父亲的颜色与之区分即可。

  若 \(d_u=2\),即链。怎么区分上下呢……我们考虑用一串循环颜色构造一个“通行方向箭头”,这样能让猫在走了一定的远路之后,可以认出箭头的指向继而调转方向。可见,“箭头”需要满足:所有由其循环同构串作为循环节的串不存在长度 \(\ge\lfloor\frac{B}2\rfloor+2\) 的回文子串。说人话呢,算上起点,猫最多用长度为 \(\lfloor\frac{B}2\rfloor+1\) 的链“认路”,那么猫最多看到 \(\lfloor\frac{B}2\rfloor+2\) 条边的颜色。如果颜色是回文,还是认不出路,就失败啦!

  一种可行的“箭头”是 0 0 1 1 0 1,恰好满足条件(0 1 1 0 为最长回文,长度为 \(4\))。

\(\mathcal{Part~2-Code}\)

namespace Task2 {

const int dir[] { 0, 0, 1, 1, 0, 1 };
vecint ans; inline void direct ( const int u, const int f, const int clen, const int curc ) {
// clen为链长(不在链上则为0),curc是若u不在链上时需要为向儿子的边染的颜色。
if ( ! ~ f ) {
for ( pii v: graph[u] ) {
ans[v.second] = 0;
direct ( v.first, u, ( int ) graph[u].size () == 1, 1 );
}
return ;
}
if ( ( int ) graph[u].size () == 2 ) {
for ( pii v: graph[u] ) if ( v.first ^ f ) {
ans[v.second] = dir[clen % 6];
direct ( v.first, u, clen + 1, ans[v.second] ^ 1 );
}
return ;
}
for ( pii v: graph[u] ) if ( v.first ^ f ) {
ans[v.second] = curc;
direct ( v.first, u, 0, ans[v.second] ^ 1 );
}
} inline vecint main () {
ans.resize ( m );
direct ( 0, -1, 0, 0 );
return ans;
} } // namespace RybyA::Task2.

\(\mathcal{Catherine}\)

  大 模 拟 !

\(\mathcal{Part~1}\)

  显。(因为下一部分太复杂 qwq……

\(\mathcal{Part~1-Code}\)

namespace Task1 {

inline int main ( vecint Y ) {
// last 为上一次走的颜色,Part2同理。
int cnt = 0;
if ( ~ last ) ++ Y[last];
for ( int y: Y ) cnt += !! y;
if ( cnt == 1 ) last = Y[2] ? 2 : !! Y[1];
else {
for ( int i = 0; i < 3; ++ i ) {
if ( ! Y[i] ) {
last = ( i + 1 ) % 3;
break;
}
}
}
return last;
} } // namespace RybyC::Task1.

\(\mathcal{Part~2}\)

  首先,记录是否已经定好方向。若已定向,无脑走即可。若未定向且当前点仍在链上,则全局用一个 std::vector 记下经过的箭头颜色。当 std::vectorsize() 为 \(5\),就一定可以定向了,打表判一判即可。

  反正……亿点细节,见代码吧(绝望 qwq。

\(\mathcal{Part~2-Code}\)

namespace Task2 {

const int down[6][5] {
{ 0, 0, 1, 1, 0 },
{ 0, 1, 1, 0, 1 },
{ 1, 1, 0, 1, 0 },
{ 1, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 1 },
{ 1, 0, 0, 1, 1 }
};
vecint chain;
bool directed; inline int main ( vecint Y ) { // 注意需要在外部用返回值更新last。
if ( ! ~ last ) {
if ( Y[0] + Y[1] == 2 ) {
if ( ! Y[1] ) {
chain.push_back ( 0 ), chain.push_back ( 0 );
return 0;
} else if ( ! Y[0] ) {
chain.push_back ( 1 ), chain.push_back ( 1 );
return 1;
} else {
chain.push_back ( 1 ), chain.push_back ( 0 );
return 0;
}
}
if ( ! Y[0] ) return directed = true, 1;
if ( ! Y[1] ) return directed = true, 0;
return directed = true, Y[1] == 1;
}
if ( ! Y[0] && ! Y[1] ) return directed = true, -1;
if ( ! directed ) {
if ( Y[0] + Y[1] > 1 ) {
directed = true;
if ( ! Y[0] || ! Y[1] ) return -1;
return ! last;
}
chain.push_back ( Y[1] );
if ( chain.size () == 5 ) {
bool downing = false; directed = true;
for ( int i = 0; ! downing && i < 6; ++ i ) {
int j = 0;
for ( ; j < 5; ++ j ) if ( down[i][j] ^ chain[j] ) break;
if ( j == 5 ) downing = true;
}
if ( downing ) return -1;
}
return chain.back ();
} else {
if ( ! Y[0] ) return 1;
if ( ! Y[1] ) return 0;
++ Y[last];
return Y[1] == 1;
}
} } // namespace RybyC::Task2. } // namespace RybyC.

\(\mathcal{Code}\)

// Anthony.cpp

#include <queue>
#include <vector>
#include <iostream>
#include "Anthony.h" #ifndef vecint
#define vecint std::vector<int>
#endif
#ifndef pii
#define pii std::pair<int, int>
#endif namespace RybyA { const int MAXN = 2e4;
int n, m, dist[MAXN + 5];
std::vector<pii> graph[MAXN + 5]; namespace Task1 { bool vis[MAXN + 5]; inline vecint main ( vecint U, vecint V ) {
std::queue<int> que;
que.push ( 0 ), vis[0] = true;
while ( ! que.empty () ) {
int u = que.front (); que.pop ();
for ( pii v: graph[u] ) if ( ! vis[v.first] ) {
dist[v.first] = dist[u] + 1;
que.push ( v.first ), vis[v.first] = true;
}
}
vecint ret ( m );
for ( int i = 0; i < m; ++ i ) ret[i] = std::min ( dist[U[i]], dist[V[i]] ) % 3;
return ret;
} } // namespace RybyA::Task1. namespace Task2 { const int dir[] { 0, 0, 1, 1, 0, 1 };
vecint ans; inline void direct ( const int u, const int f, const int clen, const int curc ) {
if ( ! ~ f ) {
for ( pii v: graph[u] ) {
ans[v.second] = 0;
direct ( v.first, u, ( int ) graph[u].size () == 1, 1 );
}
return ;
}
if ( ( int ) graph[u].size () == 2 ) {
for ( pii v: graph[u] ) if ( v.first ^ f ) {
ans[v.second] = dir[clen % 6];
direct ( v.first, u, clen + 1, ans[v.second] ^ 1 );
}
return ;
}
for ( pii v: graph[u] ) if ( v.first ^ f ) {
ans[v.second] = curc;
direct ( v.first, u, 0, ans[v.second] ^ 1 );
}
} inline vecint main () {
ans.resize ( m );
direct ( 0, -1, 0, 0 );
return ans;
} } // namespace RybyA::Task2. } // namespace RybyA. vecint Mark ( const int N, const int M, const int A, const int B, vecint U, vecint V ) {
RybyA::n = N, RybyA::m = M;
for ( int i = 0; i < M; ++ i ) {
RybyA::graph[U[i]].push_back ( { V[i], i } );
RybyA::graph[V[i]].push_back ( { U[i], i } );
}
if ( A > 2 ) return RybyA::Task1::main ( U, V );
return RybyA::Task2::main ();
} // main () {}
// Catherine.cpp

#include <vector>
#include <assert.h>
#include "Catherine.h" #ifndef vecint
#define vecint std::vector<int>
#endif
#ifndef pii
#define pii std::pair<int, int>
#endif namespace RybyC { bool type;
int last; namespace Task1 { inline int main ( vecint Y ) {
int cnt = 0;
if ( ~ last ) ++ Y[last];
for ( int y: Y ) cnt += !! y;
if ( cnt == 1 ) last = Y[2] ? 2 : !! Y[1];
else {
for ( int i = 0; i < 3; ++ i ) {
if ( ! Y[i] ) {
last = ( i + 1 ) % 3;
break;
}
}
}
return last;
} } // namespace RybyC::Task1. namespace Task2 { const int down[6][5] {
{ 0, 0, 1, 1, 0 },
{ 0, 1, 1, 0, 1 },
{ 1, 1, 0, 1, 0 },
{ 1, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 1 },
{ 1, 0, 0, 1, 1 }
};
vecint chain;
bool directed; inline int main ( vecint Y ) {
if ( ! ~ last ) {
if ( Y[0] + Y[1] == 2 ) {
if ( ! Y[1] ) {
chain.push_back ( 0 ), chain.push_back ( 0 );
return 0;
} else if ( ! Y[0] ) {
chain.push_back ( 1 ), chain.push_back ( 1 );
return 1;
} else {
chain.push_back ( 1 ), chain.push_back ( 0 );
return 0;
}
}
if ( ! Y[0] ) return directed = true, 1;
if ( ! Y[1] ) return directed = true, 0;
return directed = true, Y[1] == 1;
}
if ( ! Y[0] && ! Y[1] ) return directed = true, -1;
if ( ! directed ) {
if ( Y[0] + Y[1] > 1 ) {
directed = true;
if ( ! Y[0] || ! Y[1] ) return -1;
return ! last;
}
chain.push_back ( Y[1] );
if ( chain.size () == 5 ) {
bool downing = false; directed = true;
for ( int i = 0; ! downing && i < 6; ++ i ) {
int j = 0;
for ( ; j < 5; ++ j ) if ( down[i][j] ^ chain[j] ) break;
if ( j == 5 ) downing = true;
}
if ( downing ) return -1;
}
return chain.back ();
} else {
if ( ! Y[0] ) return 1;
if ( ! Y[1] ) return 0;
++ Y[last];
return Y[1] == 1;
}
} } // namespace RybyC::Task2. } // namespace RybyC. void Init ( int A, int B ) { RybyC::last = -1, RybyC::type = A > 2; } int Move ( vecint Y ) {
if ( RybyC::type ) return RybyC::Task1::main ( Y );
else {
int t = RybyC::Task2::main ( Y );
if ( ~ t ) RybyC::last = t;
return t;
}
} // main () {}

Solution -「JOISC 2020」「UOJ #509」迷路的猫的更多相关文章

  1. 「JOISC 2020 Day2」变态龙之色 题解

    题目传送门 注意 同性必定不同色 必有一个同色异性,且不相互不喜欢 Solution 我们发现,我们问题比较大的就是如何确定性别问题.我们可以一个一个加进去,在原来已经确定了的二分图上增加新的性别关系 ...

  2. 「JOISC 2020 Day1」汉堡肉

    我终于学会打开机房的LOJ了! description LOJ3272 有\(n(n<=2*10^5)\)个矩形,让你找\(k(k<=4)\)个点可以覆盖所有矩形(点可重复),输出一种方案 ...

  3. 「JOISC 2020 Day4」首都城市

    题目   点这里看题目. 分析   做法比较容易看出来.我们对于每个城市,找出那些 " 如果这个城市在首都内,则必须在首都内的其它城市 " ,也就是为了让这个城市的小镇连通而必须选 ...

  4. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

  5. Loj #2731 「JOISC 2016 Day 1」棋盘游戏

    Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...

  6. 「JOISC 2019 Day3」穿越时空 Bitaro

    「JOISC 2019 Day3」穿越时空 Bitaro 题解: ​ 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. ​ 问题变成二维平面上 ...

  7. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  8. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  9. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

随机推荐

  1. 原生android webview 显示的H5页面颜色属性无法识别 - 具体解决心得

    1.前言 background-color: #fc1717bf; 这个样式属性没毛病吧,浏览器都是支持的,但是在android 7.0 系统无法正确识别这个含有透明度的属性, 即bf无法识别,将默认 ...

  2. LaTex用法笔记(一)——LaTex源文件的基本结构

    首先打开TeXstudio,创建一个新文件并保存 用\documentclass{article}引入一个文档类,也可以引用book/report/letter 然后用\begin{}和\end{}输 ...

  3. gin中自定义中间件

    package main import ( "github.com/gin-gonic/gin" "log" "time" ) func L ...

  4. 返回值Student-Json

    MyController中 index.jsp 修改url

  5. 源码分析axios(1)~源码分析、模拟axios的创建

    ■ 查看源码发现,起初axios[instance=bind(Axios.prototype.request, context);]是一个函数, 但后续[ utils.extend(instance, ...

  6. Homework_2

    禁 止 吃 瓜 我是小鱼 刚才有个同学问我小鱼发生肾么事了 我说怎么回事? 给我发了一个张截图,我一看! 噢!原来是昨天发布第二次寒假作业了 我大一了啊没有闪 来!偷袭!我三岁的小同志 当时就流眼泪了 ...

  7. Fiddler初学笔记

    Fiddler简介 Fiddller官网: www.fiddler2.com Fiddler是客户端与服务器端的http代理,是目前最常用的http抓包工具之一. Fiddler能够监听客户端和服务器 ...

  8. STS中创建 javaweb 项目?

    package com.aaa.readme; /* * 一. * 1.安装Tomcat 版本8.5 * * 2.file---->new------>dynamic java web p ...

  9. AtCoder ABC213 简要题解

    这世道连 \(\rm ABC\) 都要写题解来续命了... A - D 略. E 有如下观察: 对于任意的四个方格,出去之后再回来可以调整为先在内部走到固定位置再走出去. 因此只需要考虑在一开始把内部 ...

  10. windows10使用wireshark抓取本机请求包

    1.管理员运行cmd 右键左下角windows图标,管理员运行Windows PowerShell 2.输入ipconfg查看本机ip和网关ip 3.执行命令 route add 本机ip mask ...