首页 > 其他分享 >洛谷 P9869 [NOIP2023] 三值逻辑 题解

洛谷 P9869 [NOIP2023] 三值逻辑 题解

时间:2024-01-19 19:25:08浏览次数:41  
标签:P9869 ch 洛谷 int 题解 LL sgn REP dis

Solution

  • 模拟程序,容易发现每个点最后的取值都是定值或一个点的初始值(可能是该值取反)。
  • 最后是定值的点可以确定初始值,最后取值由该点决定的点也可以确定取值。求出这些取值,答案加上取之为 U 的点的个数。
  • 即第 \(i\) 个点最后的取值是 \(to_i\) 的初始值,\(sg_i\) 表示是否取反,那么连一条 \((i,to)\) 权值为 \(sg_i\) 的无向边。若 \(i\) 的取值是定值,忽略。
  • 枚举每个连通块,可以发现确定连通块内一个点的初始值即可确定连通块内其他点的初始值。BFS 判断是否存在权值为奇数的环,若存在说明整个连通块取值为 U,答案加上连通块大小。

时间复杂度 \(\mathcal{O}(n+m)\)。

Code

#include <bits/stdc++.h>
#define REP(i, l, r) for (int i = (l); i <= (r); ++ i)
#define DEP(i, r, l) for (int i = (r); i >= (l); -- i)
#define fi first
#define se second
using namespace std;
namespace Milkcat {
    typedef long long LL;
    typedef pair<LL, LL> pii;
    const int N = 2e5 + 5;
    struct Graph {
	    struct edge { LL from, to, w, next; } e[N]; LL cnt, head[N];
	    void ins(LL u, LL v, LL w = 0) { e[++ cnt] = {u, v, w, head[u]}, head[u] = cnt; }
	    void clear() { memset(head, 0, sizeof head), cnt = 0; }
	    #define FEG(u, v, W, G, i) \
	        for (LL i = G.head[u], v = G.e[i].to, W = G.e[i].w; i; i = G.e[i].next, v = G.e[i].to, W = G.e[i].w)
	} G, E;
	LL n, m, u, v, ans, to[N], val[N], sgn[N], dis[N], vis[N];
	char ch;
	int XOR(int u, int sg) { return (u == 2 ? u : (u ^ sg)); }
	void dfs(int u, int w) {
		val[u] = w;
		FEG(u, v, sg, G, i) dfs(v, XOR(w, sg));
	}
    int main() {
		cin >> n >> m;
		REP(i, 1, n) to[i] = i;
		REP(i, 1, m) {
			cin >> ch;
			if (ch == '+') cin >> u >> v, to[u] = to[v], sgn[u] = sgn[v];
			if (ch == '-') cin >> u >> v, to[u] = to[v], sgn[u] = sgn[v] ^ 1;
			if (ch == 'T') cin >> u, to[u] = -1, sgn[u] = 0;
			if (ch == 'F') cin >> u, to[u] = 0, sgn[u] = 0;
			if (ch == 'U') cin >> u, to[u] = -2, sgn[u] = 0;
		}
		REP(i, 1, n)
			if (to[i] > 0) G.ins(to[i], i, sgn[i]);
		memset(val, -1, sizeof val);
		REP(i, 1, n)
			if (to[i] < 1) dfs(i, -to[i]);
		REP(i, 1, n) {
			if (val[i] >= 0) ans += (val[i] == 2), vis[i] = 1;
			else E.ins(i, to[i], sgn[i]), E.ins(to[i], i, sgn[i]);
		}
		
		auto BFS = [&](int s) {
			queue<int> q; vector<int> st; bool success = 1;
			dis[s] = 0, q.push(s), st.push_back(s);
			while (!q.empty()) {
				int u = q.front(); q.pop();
				FEG(u, v, w, E, i) {
					if (dis[v] == -1) dis[v] = dis[u] ^ w, q.push(v), st.push_back(v);
					else if (dis[v] != (dis[u] ^ w)) success = 0;
				}
			}
			for (int u : st) dis[u] = -1, vis[u] = 1;
			if (!success) ans += st.size();
		};
		memset(dis, -1, sizeof dis);
		REP(i, 1, n)
			if (!vis[i]) BFS(i);
		cout << ans << '\n';
		
		G.clear(), E.clear(), ans = 0;
		memset(to, 0, sizeof to);
		memset(sgn, 0, sizeof sgn);
		memset(vis, 0, sizeof vis);
		
        return 0;
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int C, T = 1; cin >> C >> T;
    while (T --) Milkcat::main();
    return 0;
}

标签:P9869,ch,洛谷,int,题解,LL,sgn,REP,dis
From: https://www.cnblogs.com/Milkcatqwq/p/17975414

相关文章

  • 洛谷 P9751 [CSP-J 2023] 旅游巴士 题解
    Solution能在起点等\(k\)的非负整数倍相当于能在任意点等\(k\)的非负整数倍。由于离开的时间要是\(k\)的负整数倍,将每个点拆成\(k\)个点,\(dis_{i,j}\)表示到了第\(i\)个点长度\(\bmod\text{}k\equivj\)的最短路径。转移时若时间未到,直接在原地等\(k\)的负整......
  • 洛谷 P9745 「KDOI-06-S」树上异或 题解
    Solution树形DP好题。PartI部分分类比下文为简单,我们称一个连通块的权值为连通块内点的异或和。考虑链的部分分,显然可以设\(f_{i}\)是前\(i\)个点所有断边方案的权值和,对于每个点枚举上一条断的边转移。令\(s_i=\bigoplus_{j=1}^{i}a_j\),则\(f_i=\sum_{j=0}^{i-1}(s......
  • 洛谷 P9579「Cfz Round 1」Elevator 另类题解
    一个赛时想到的另类DP做法。Solution容易将原题转化为一个人乘电梯每次上下一层。对于\(a_i<b_i\)是好处理的,记\(\displaystylem=\max_{1\leqi\leqn}\{a_i,b_i\}\),只需要跑到\(m\)即可解决所有这种条件。对于\(a_i>b_i\)的条件,我们除了到\(m\)外,还需要额外地从......
  • 洛谷 P9575 「TAOI-2」喵了个喵 Ⅳ 题解
    Solution先求出所有数的最大公约数\(d\),然后将每个数约去\(d\)。将约去后的数均分,约去前的数也均分。下文讨论的数都是约去\(d\)后的数(包括取的\(x\))。\(n\)为偶数,取\(x=1\),对半分即可。\(n\)不为偶数,且有奇数个偶数。取\(x=2\),设奇数和偶数分别有\(x,y\)个,B组取......
  • 洛谷 P9915 「RiOI-03」3-2 题解
    Preface为啥有蓝啊,这题在机房里15min左右就切了,反倒是2A做了1h。。Solution将矩阵逆时针旋转\(90^{\circ}\),你会发现这是一棵线段树,是父亲左儿子的节点颜色是\(0\),是右儿子的节点颜色是\(1\)。容易发现,联通块一定是一条链。具体地,你从给定的点向上跳,跳到第一个与自己......
  • CF1895E Infinite Card Game 题解
    Solution根据贪心策略,可以发现出完一张牌后对手的出牌是固定的。同理可以算出Monocarp出完一张牌\(a\)后下一次出的牌\(to_a\)。\(a\)和\(to_a\)胜负状态相同。可以发现对所有\(a\)建\(a\toto_a\)后形成的图是内向基环树,一遍dfs即可求出答案。时间复杂度\(\m......
  • /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found问题解决
    有一个go实现的项目代码最近有更新,自己在开发环境上手动构建并运行都没有问题(构建和运行时相同环境,肯定没有问题^_^)。后面通过jenkins构建镜像也没有问题,运行时却报错 之前的版本在jenkins上构建也是成功的,后沟通得知jenkins集群版本最近有更新 那么,大概知道原因了,由于jenk......
  • 洛谷题单指南-模拟和高精度-P1098 [NOIP2007 提高组] 字符串的展开
    原题链接:https://www.luogu.com.cn/problem/P1098题意解读:题目本身是一道模拟题,但是细节点较多,要拿100分,有以下注意点:1、-号两个需要同时为小写字母或者数字,才进行填充2、-号左边>=右边,直接输出-3、对待填充的内容的处理,可以先看是否填充*;小写字母和数字的填充都是前一位asci......
  • CF1214E题解
    PetyaandConstructionSet题目传送门题解一个构造题,结论挺容易猜的。观察到关键信息:\(d_i\len\)。所以我们先把所有奇数编号的点按对应的\(d\)从大到小组成一条链,然后依次考虑偶数号点应该接在链上的哪个点后,容易知道这个点为链上的第\(i+d-1\)个。特殊的,如果接在了最后......
  • CF150C题解
    SmartCheater题目传送门题解首先显然的,每个乘客是独立计算的,然后我们发现,一个乘客在\(i\)到\(i+1\)不买票的期望贡献是一定的,为\(\dfrac{x_{i+1}-x_i}{2}-c*p_i\),所以我们其实就是要对于每个乘客的区间求最大子段和,简单线段树板子,感觉也没啥细节。代码:#include<bits/st......