2020ICPC沈陽站C題 Mean Streets of Gadgetzan


大致題意

原題鏈接

翻譯

\(有n個邏輯變量 請你分別對它們賦值 使其滿足m個命題\)

\(命題有四種格式:\)

  • 單獨數字x 表示第x個邏輯變量為真

  • ! + 數字x 表示第x個邏輯變量為假

  • 若干個數字\(a_1, a_2, ..., a_p\)(不給出個數) -> 數字x 表示前面的a變量全為真
    的時候x必定為真

  • 若干個數字\(a_1, a_2, ..., a_p\)(不給出個數) -> ! + 數字x 表示前面的a變量全為真
    的時候x必定為假

其中每個命題之間空行 即'\n'

注: 此題含有SPJ 可能有多種方案 任意輸出一種

思路

明顯的構造吧

考慮對於1,2類的命題 直接給變量賦值

對3,4類的命題 可以發現一個性質

即當a數組其中任意一個或多個邏輯變量值為0時 命題必定成立

為了方便構造 盡量滿足 我們盡量將此類條件按上述性質處理 即讓a數組有0

那么我們只需要將全部邏輯變量初值賦值為0(false)即可

在推出一個true變量后去更新其他變量 若a數組的值全部固定不為0 則后面的x的值也固定了

注意

這題的讀入有些毒瘤

例如

image

這個時候我們可以無視掉'->'因為你判斷數的個數就可以推出是1,2類命題還是3,4類命題

運用快讀的方法讀入數字 如下:

if (isdigit(ch))
	isnum = true,
	x = (x << 1) + (x << 3) + (ch ^ 48);

當ch(讀入字符)為'!'的時候 根據命題的性質 最多有一個!所以直接用bool記錄一下

if(ch == '!') sign = 1;

總的讀入如下

void rad(int x = 0, char ch = getchar(), bool isnum = false) {
	Num.clear(); int sign = 0;
	for (; ch != '\n' && ch != '\r' && ch != EOF; ch = getchar()) {
		if (isdigit(ch))
			isnum = true,
			x = (x << 1) + (x << 3) + (ch ^ 48);
		else {
			if (isnum) Num.push_back(x);
			x = isnum = 0; if(ch == '!') sign = 1;
		}
	}
	if (isnum) Num.push_back(x);
	if (Num.size() == 1) q.push(sign ? -Num[0] : Num[0]);
	else {
		deg[++ tot] = Num.size() - 1;
		for (auto v : Num) e[v].push_back(tot);
		to[tot] = sign? -Num[deg[tot]] : Num[deg[tot]]; 
	}
}

實現

#include <bits/stdc++.h>

using namespace std;

int read(int x = 0, bool f = false, char ch = getchar()) {
	for (; !isdigit(ch); ch = getchar()) f ^= (ch == '-');
	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	return f ? ~x + 1 : x;
}

const int N = 1e6 + 5;

int m, n, tot;
int dat[N], deg[N], to[N];

queue<int> q;
vector<int> Num, e[N];

void rad(int x = 0, char ch = getchar(), bool isnum = false) {
	Num.clear(); int sign = 0;
	for (; ch != '\n' && ch != '\r' && ch != EOF; ch = getchar()) {
		if (isdigit(ch))
			isnum = true,
			x = (x << 1) + (x << 3) + (ch ^ 48);
		else {
			if (isnum) Num.push_back(x);
			x = isnum = 0; if(ch == '!') sign = 1;
		}
	}
	if (isnum) Num.push_back(x);
	if (Num.size() == 1) q.push(sign ? -Num[0] : Num[0]);
	else {
		deg[++ tot] = Num.size() - 1;
		for (auto v : Num) e[v].push_back(tot);
		to[tot] = sign? -Num[deg[tot]] : Num[deg[tot]]; 
	}
}

signed main() {
	m = read(), n = read();
	for (int i = 1; i <= m; ++i) rad();
	while(q.size()) {
		int x = q.front(); q.pop();
		if (x < 0) {
			x = -x;
			if (dat[x] > 0) return puts("conflict"), 0;
			dat[x] = -1;
		} else {
			if (dat[x] < 0) return puts("conflict"), 0;
			if (dat[x]) continue; dat[x] = 1;
			for (auto v : e[x]) {
				if (!(--deg[v])) q.push(to[v]);
			}
		}
	} for (int i = 1; i <= n; ++i) putchar(dat[i] == 1? 'T' : 'F');
	return 0;
}

如果喜歡的話 點個贊再走吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM