首页 > 其他分享 >题解 CF1887E【Good Colorings】

题解 CF1887E【Good Colorings】

时间:2023-12-15 21:34:53浏览次数:36  
标签:return int 题解 CF1887E cyc operator Modint Colorings friend

萌萌交互题。

对网格图进行二分图建模,左部 \(n\) 个点表示每一行,右部 \(n\) 个点表示每一列。若格子 \((i,j)\) 被染成 \(c\) 色,就连接 \((L_i,R_j,c)\) 的边。

由抽屉原理易证,在初始局面中至少有一个各边颜色均不同的偶环。获胜条件相当于存在一个各边颜色均不同的四元环。

讨论环长是否为四的倍数。若不为四的倍数,则询问任意一对正对面的点对应的格子;若为四的倍数,错开一位即可。(如图所示)

这样,我们就可以将大环划分为两个大小约为一半的小环。显然,无论询问的边被染成什么颜色,两个小环之中至少有一个不包含这种颜色。在第一个图中为左半部分,在第二个图中为右半部分。

至此,我们可以由一个各边颜色均不同的偶环,经过一次询问,得到一个规模减半的各边颜色依然不同的偶环。重复询问直到环长为四,最大询问次数不超过 \(10\)。

需要注意的一点是,在每组数据结束后,需要读入一行字符串 OK

// Problem: Good Colorings
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1887E
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x, y, z) for(int x = (y); x <= (z); ++x)
#define per(x, y, z) for(int x = (y); x >= (z); --x)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do {freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);} while(false)
#define endl '\n'
using namespace std;
typedef long long ll;

mt19937 rnd(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
int randint(int L, int R) {
    uniform_int_distribution<int> dist(L, R);
    return dist(rnd);
}

template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

template<int mod>
inline unsigned int down(unsigned int x) {
	return x >= mod ? x - mod : x;
}

template<int mod>
struct Modint {
	unsigned int x;
	Modint() = default;
	Modint(unsigned int x) : x(x) {}
	friend istream& operator>>(istream& in, Modint& a) {return in >> a.x;}
	friend ostream& operator<<(ostream& out, Modint a) {return out << a.x;}
	friend Modint operator+(Modint a, Modint b) {return down<mod>(a.x + b.x);}
	friend Modint operator-(Modint a, Modint b) {return down<mod>(a.x - b.x + mod);}
	friend Modint operator*(Modint a, Modint b) {return 1ULL * a.x * b.x % mod;}
	friend Modint operator/(Modint a, Modint b) {return a * ~b;}
	friend Modint operator^(Modint a, int b) {Modint ans = 1; for(; b; b >>= 1, a *= a) if(b & 1) ans *= a; return ans;}
	friend Modint operator~(Modint a) {return a ^ (mod - 2);}
	friend Modint operator-(Modint a) {return down<mod>(mod - a.x);}
	friend Modint& operator+=(Modint& a, Modint b) {return a = a + b;}
	friend Modint& operator-=(Modint& a, Modint b) {return a = a - b;}
	friend Modint& operator*=(Modint& a, Modint b) {return a = a * b;}
	friend Modint& operator/=(Modint& a, Modint b) {return a = a / b;}
	friend Modint& operator^=(Modint& a, int b) {return a = a ^ b;}
	friend Modint& operator++(Modint& a) {return a += 1;}
	friend Modint operator++(Modint& a, int) {Modint x = a; a += 1; return x;}
	friend Modint& operator--(Modint& a) {return a -= 1;}
	friend Modint operator--(Modint& a, int) {Modint x = a; a -= 1; return x;}
	friend bool operator==(Modint a, Modint b) {return a.x == b.x;}
	friend bool operator!=(Modint a, Modint b) {return !(a == b);}
};

const int N = 2e3 + 5;

int T, n, col[N][N], vis[N];
vector<int> e[N], cyc;
stack<int> stk;

bool dfs(int u, int f) {
    vis[u] = 1;
    stk.push(u);
    for(int v : e[u]) {
        if(v == f || vis[v] == 2) continue;
        if(vis[v] == 1) {
            if(v <= n) cyc.push_back(v);
            while(stk.top() != v) {
                cyc.push_back(stk.top());
                stk.pop();
            }
            if(v > n) cyc.push_back(v);
            return true;
        }
        if(dfs(v, u)) return true;
    }
    vis[u] = 2;
    stk.pop();
    return false;
}

void solve() {
    cin >> n;
    rep(i, 1, 2 * n) {
        int u, v;
        cin >> u >> v;
        e[u].push_back(n + v);
        e[n + v].push_back(u);
        col[u][n + v] = i;
        col[n + v][u] = i;
    }
    rep(i, 1, 2 * n) if(vis[i] == 0) if(dfs(i, 0)) break;
    while(cyc.size() > 4) {
        int sz = cyc.size();
        int uid = 0, vid = sz % 4 == 0 ? sz / 2 + 1 : sz / 2;
        int u = cyc[uid], v = cyc[vid], c;
        cout << "? " << u << " " << v - n << endl << flush;
        cin >> c;
        col[u][v] = col[v][u] = c;
        bool flag = true;
        rep(i, uid, vid - 1) if(col[cyc[i]][cyc[i + 1]] == c) flag = false;
        vector<int> tmp;
        if(flag) {
            rep(i, uid, vid) tmp.push_back(cyc[i]);
        }
        else {
            tmp.push_back(cyc[uid]);
            per(i, cyc.size() - 1, vid) tmp.push_back(cyc[i]);
        }
        swap(cyc, tmp);
    }
    cout << "! " << cyc[0] << " " << cyc[2] << " " << cyc[1] - n << " " << cyc[3] - n << endl << flush;
    string result;
    cin >> result;
    assert(result == "OK");
}

void clear() {
    rep(i, 1, 2 * n) {
        rep(j, 1, 2 * n) col[i][j] = 0;
        vis[i] = 0;
        e[i].clear();
    }
    cyc.clear();
    while(!stk.empty()) stk.pop();
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    for(cin >> T; T; --T) {
        solve();
        clear();
    }
    return 0;
}

标签:return,int,题解,CF1887E,cyc,operator,Modint,Colorings,friend
From: https://www.cnblogs.com/ruierqwq/p/CF-1887E.html

相关文章

  • 洛谷P1824 进击的奶牛 题解 二分答案
    题目链接:https://www.luogu.com.cn/problem/P1824题目大意:本题相当于在\(n\)个数中选\(c\)个数,使得这\(c\)个数中相差最小的两个数之差尽可能地大。解题思路:我们首先可以给\(a_1\sima_n\)从小到大排一下序(这里有点贪心的思想,你会发现很多涉及贪心的问题在排序之后解......
  • ABC332G Not Too Many Balls 题解
    第\(i\)种球有\(a_i\)个,共\(n\)种。第\(i\)种箱子最多共装\(b_i\)个球。共\(m\)种。第\(i\)种球在第\(j\)种箱子里至多放\(ij\)个。问所有箱子放的球数最多是多少。\(1\leqn\leq500,1\leqm\leq5e5,0\leqa_i,b_i\leq1e12\)。很容易建出网络流模型。......
  • CF1784C Monsters (hard version) 题解 线段树
    题目链接:https://codeforces.com/problemset/problem/1784/C题目大意:你面前有\(n\)只怪兽,每只怪兽都有一个初始血量,你可以进行两类操作:操作1:选择任意一个血量大于\(0\)的怪兽,并将它的血量降低\(1\);操作2:将所有存活的怪物的血量各自减去\(1\),如果存在怪物的血量恰好降为......
  • PTA-2023第十三次练习题目题解
    PTA-2023第十三次练习题目题解以下代码已做防抄袭处理,切勿抄袭。注意:手机端因为屏幕限制,代码会有(不希望的)换行。解决方案:1.建议使用电脑端打开。2.点击代码进入全屏观看。6-25实验9_5_反向打印字符串思路就是每次先找到字符串的最后一位,然后输出这一位,输出之后将这一位改为‘......
  • P8818 [CSP-S 2022] 策略游戏 题解
    P8818[CSP-S2022]策略游戏题解题目链接P8818[CSP-S2022]策略游戏简化题意小\(A\)先在\(a[l1,r1]\)中选择一个数\(x\),小\(B\)再在\(b[l2,r2]\)中选择一个数\(y\),最后的分数就是\(x\timesy\)。小\(A\)想让分数尽可能地大,而小\(B\)则想让分数尽可能地小......
  • 【问题解决】unable to do port forwarding: socat not found
    问题复现前阵子应公司要求做华为云平台的调研,写了一篇文档包含将华为云CCE下载kuberctl配置及使用kubectl转发流量到本地的操作。今天一早上同事就发来一个错误界面,说是Java远程调试转发过来的端口出现问题,如下图:处理思路最初以为是容器镜像未安装socat所致,安装重新打镜像后......
  • 12月13日80端口被占用问题解决
    在写软件构造作业的时候,发现Jfinal提示java.lang.IllegalStateException:port:80notavailable!原因是因为我们的80端口被占用了,当我们输入localhost的时候出现的是windows iis服务的界面这个时候需要我们关闭windowsiis服务1.点击开始收索服务,在服务界面找到worldWide......
  • luogu1972题解
    还是先写被卡的做法吧。节点的区间用了现用现计算卡常过了。被卡了一上午,难过。话说有人说我码风有点抽象。思路主席树做法。a[i]是贝壳序列。先求出nxt,即与a[i]相同的下一个a[j]的下标j。用p114514[i]记了值为\(i\)的数的下标,循环到序列第\(j\)个数的时候,先......
  • Vue + Element UI 实现复制当前行数据功能(复制到新增页面组件值不能更新等问题解决)
    1、需求使用Vue+ElementUI实现在列表的操作栏新增一个复制按钮,复制当前行的数据可以打开新增弹窗后亦可以跳转到新增页面,本文实现为跳转到新增页面。2、实现1)列表页index.vue<el-table><!--其他列--><el-table-columnlabel="操作"width="150"><templateslot-scope=......
  • [CF980D] Perfect Groups 题解
    [CF980D]PerfectGroups题解思路第一个观察就很难观察到:\[ab=x^2,bc=y^2\Longrightarrow\existz,ac=z^2(a,b,c\ne0)\]证明:两个条件式相乘得到:\[ab^2c=x^2y^2\\ac=\dfrac{x^2y^2}{b^2}(b\ne0)\\\becauseb|x^2,b|y^2\\\thereforeb^2|x^2y^2......