当前位置:网站首页>【luogu P8326】Fliper(图论)(构造)(欧拉回路)
【luogu P8326】Fliper(图论)(构造)(欧拉回路)
2022-07-31 16:30:00 【SSL_TJH】
Fliper
题目链接:luogu P8326
题目大意
平面上有 n 个挡板(分左上到右下和右上到左下),如果小球碰到会 90 度改变轨迹。
然后你要给每个挡板一个颜色,使得对于每个循环的反弹序列,满足每个颜色的挡板出现次数相同而且是偶数。(如果一个挡板在序列中出现两次算两次)
如果无法构造方案输出 -1。
思路
首先考虑找出循环。
那就是把一个挡板分成两个点(两面),然后连一个同色边表示这个边的颜色确定挡板的颜色。
然后你把从一面弹回到令一个地方的一个面的两个点连边,然后把这个给缩点一下。
那就会形成一些大点(表示循环序列),以及一些其他的点(不在循环序列中),那我们把它连向一个 i n f \rm inf inf 点。
然后考虑染色,会发现你要满足所有的循环序列,如果暴力搞可以解方程但是复杂度也太大了。
考虑找点性质,那这是一个图我们就找点图论的性质。
发现有解的情况我们看看是则那样的,不难想到情况是每个大点的度数要是 8 8 8 的倍数。
然后图论中有一个性质就是度数为奇数的点总是有偶数个的。
然后我们就可以得出 i n f \rm inf inf 点的度数一定也是偶数。(如果是奇数那就只有 1 1 1 个点,不是偶数个)
那不难想到一个东西叫做欧拉回路。
考虑找出欧拉回路然后黑白染色,那我们就分成了两种颜色。
那不难接下来想出分出四种的做法:因为这样之后度数是 4 4 4 的倍数,所以也是存在欧拉回路的。(根据上面的图论性质也会有 i n f \rm inf inf 点度数为偶数)
那我们就对分出的两个颜色的图分别再跑一个欧拉回路,就分成四种了。
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 5e5 + 1000;
/* op=0: / , op=1: \ */
/* i / n+i i \ n+i */
struct node {
int x, y, op, id;
}a[N];
int n, col[N * 2], tot;
int ans[N], KK_, sta[N * 2], du[N * 2];
vector <int> G[N * 2], F[N * 2], F_[N * 2];
bool in[N * 2], use[N * 2];
int zf, re; char c;
int read() {
zf = 1; re = 0; c = getchar();
while (c < '0' || c > '9') {
if (c == '-') zf = -zf;
c = getchar();
}
while (c >= '0' && c <= '9') {
re = (re << 3) + (re << 1) + c - '0';
c = getchar();
}
return re * zf;
}
bool cmpx(node x, node y) {
if (x.x != y.x) return x.x < y.x; return x.y < y.y;}
bool cmpy(node x, node y) {
if (x.y != y.y) return x.y < y.y; return x.x < y.x;}
void add(int x, int y) {
G[x].push_back(y); G[y].push_back(x);
}
//0:光线边
//1:同色边
//2:INF边
bool Find;
void dfs(int now, int father) {
sta[++sta[0]] = now; in[now] = 1;
for (int i = 0; i < G[now].size(); i++)
if (G[now][i] != father) {
if (in[G[now][i]]) {
tot++; Find = 1;
while (sta[0]) col[sta[sta[0]]] = tot, sta[0]--;
return ;
}
else dfs(G[now][i], now);
if (Find) return ;
}
}
void Add(int x, int y, int z) {
F[x].push_back(y); if (x != y) F[y].push_back(x);
F_[x].push_back(z); if (x != y) F_[y].push_back(z);
du[x]++; du[y]++;
}
void Link() {
sort(a + 1, a + n + 1, cmpy);
for (int L = 1, R; L <= n; L = R + 1) {
R = L; while (R < n && a[R + 1].y == a[L].y) R++;
for (int i = L; i < R; i++) {
add(n + a[i].id, a[i + 1].id);
}
}
sort(a + 1, a + n + 1, cmpx);
for (int L = 1, R; L <= n; L = R + 1) {
R = L; while (R < n && a[R + 1].x == a[L].x) R++;
for (int i = L; i < R; i++) {
if (a[i].op == 0 && a[i + 1].op == 0) add(a[i].id, n + a[i + 1].id);
if (a[i].op == 0 && a[i + 1].op == 1) add(a[i].id, a[i + 1].id);
if (a[i].op == 1 && a[i + 1].op == 0) add(n + a[i].id, n + a[i + 1].id);
if (a[i].op == 1 && a[i + 1].op == 1) add(n + a[i].id, a[i + 1].id);
}
}
for (int i = 1; i <= 2 * n; i++)
if (!in[i]) {
sta[0] = 0, Find = 0, dfs(i, 0);
if (!Find) {
while (sta[0]) use[sta[sta[0]]] = 1, sta[0]--;
}
}
for (int i = 1; i <= n; i++) {
int x = use[i] ? 2 * n + 1 : col[i];
int y = use[n + i] ? 2 * n + 1 : col[n + i];
Add(x, y, i);
}
}
bool check_ans() {
for (int i = 1; i <= tot; i++)
if (du[i] % 8 != 0) return 0;
return 1;
}
struct nde {
int id, to, nxt;
}e[N * 2];
int in_[N * 2], le[N * 2], KK;
void run_way(int now) {
for (int i = le[now]; i; i = le[now]) {
le[now] = e[i].nxt;
if (in_[e[i].id]) continue; in_[e[i].id] = 1;
run_way(e[i].to); sta[++sta[0]] = e[i].id;
}
}
void get_oula() {
memset(in_, 0, sizeof(in_)); sta[0] = 0;
run_way(2 * n + 1);
for (int i = 1; i <= tot; i++) run_way(i);
for (int i = 1; i <= sta[0]; i += 2)
in_[sta[i]]++;
}
void clear() {
KK = 0; memset(le, 0, sizeof(le));
}
void slove() {
clear();
for (int i = 1; i <= 2 * n + 1; i++)
for (int j = 0; j < F[i].size(); j++)
e[++KK] = (nde){
F_[i][j], F[i][j], le[i]}, le[i] = KK;
get_oula();
for (int i = 1; i <= n; i++) ans[i] = in_[i] * 2;
clear();
for (int i = 1; i <= 2 * n + 1; i++)
for (int j = 0; j < F[i].size(); j++)
if (ans[F_[i][j]] == 2)
e[++KK] = (nde){
F_[i][j], F[i][j], le[i]}, le[i] = KK;
get_oula();
for (int i = 1; i <= n; i++) if (in_[i]) ans[i] += in_[i] - 2;
clear();
for (int i = 1; i <= 2 * n + 1; i++)
for (int j = 0; j < F[i].size(); j++)
if (ans[F_[i][j]] == 4)
e[++KK] = (nde){
F_[i][j], F[i][j], le[i]}, le[i] = KK;
get_oula();
for (int i = 1; i <= n; i++) if (in_[i]) ans[i] += in_[i] - 2;
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
}
int main() {
// freopen("pinball.in", "r", stdin);
// freopen("pinball.out", "w", stdout);
n = read();
for (int i = 1; i <= n; i++) {
a[i].x = read(); a[i].y = read(); a[i].id = i;
char c = getchar(); while (c != '\\' && c != '/') c = getchar();
if (c == '/') a[i].op = 0; else a[i].op = 1;
}
Link();
if (!check_ans()) {
printf("-1"); return 0;}
slove();
return 0;
}
边栏推荐
- Precautions and solutions when SIGABRT error is reported
- i.MX6ULL driver development | 33 - NXP original network device driver reading (LAN8720 PHY)
- 复制延迟案例(1)-最终一致性
- 最新神作!阿里巴巴刚出炉的面试参考指南(泰山版),我直接狂刷29天
- gerrit中如何切换远程服务器
- 【7.28】代码源 - 【Fence Painting】【合适数对(数据加强版)】
- 牛客 HJ18 识别有效的IP地址和掩码并进行分类统计
- Applicable scenario of multi-master replication (2) - client and collaborative editing that require offline operation
- C语言-函数
- Kubernetes principle analysis and practical application manual, too complete
猜你喜欢
Implementing distributed locks based on Redis (SETNX), case: Solving oversold orders under high concurrency
MySQL基础篇【单行函数】
mysql black window ~ build database and build table
Graham‘s Scan法求解凸包问题
After Grafana is installed, the web opens and reports an error
宁波大学NBU IT项目管理期末考试知识点整理
使用 Postman 工具高效管理和测试 SAP ABAP OData 服务的试读版
GP 6总体架构学习笔记
第05章 存储引擎【1.MySQL架构篇】【MySQL高级】
2022年必读的12本机器学习书籍推荐
随机推荐
Handling write conflicts under multi-master replication (4) - multi-master replication topology
MySQL database operations
MySQL常用语句整理
牛客网刷题(四)
type of timer
TypeError: unhashable type: ‘list‘
js的toString方法
Baidu cloud web speed playback (is there any website available)
6-22漏洞利用-postgresql数据库密码破解
对话庄表伟:开源第一课
2020微信小程序反编译教程(小程序反编译源码能用吗)
Applicable scenario of multi-master replication (2) - client and collaborative editing that require offline operation
Premiere Pro 2022 for (pr 2022)v22.5.0
二分查找的细节坑
第二届中国PWA开发者日
tooltips使用教程(鼠标悬停时显示提示)
入职一个月反思
[Meetup Preview] OpenMLDB+OneFlow: Link feature engineering to model training to accelerate machine learning model development
SringMVC中个常见的几个问题
深度学习机器学习理论及应用实战-必备知识点整理分享