UOJ317 NOI2017 遊戲 題解

2022-05-07 19:00:09 字數 4485 閱讀 6665

​ 小 l 計畫進行 \(n\) 場遊戲,每場遊戲使用一張地圖,小 l 會選擇一輛車在該地圖上完成遊戲。

​ 小 l 的賽車有三輛,分別用大寫字母 a、b、c 表示。地圖一共有四種,分別用小寫字母 x、a、b、c 表示。其中,賽車 a 不適合在地圖 a 上使用,賽車 b 不適合在地圖 b 上使用,賽車 c 不適合在地圖 c 上使用,而地圖 x 則適合所有賽車參加。適合所有賽車參加的地圖並不多見,最多隻會有 \(d\) 張。

​ \(n\) 場遊戲的地圖可以用乙個小寫字母組成的字串描述。例如:\(\underline\) 表示小 l 計畫進行 8 場遊戲,其中第 1 場和第 5 場的地圖型別是 x,適合所有賽車,第 2 場和第 3 場的地圖是 a,不適合賽車 a,第 4 場和第 7 場的地圖是 b,不適合賽車 b,第 6 場和第 8 場的地圖是 c,不適合賽車 c。

​ 小 l 對遊戲有一些特殊的要求(共 \(m\) 條),這些要求可以用四元組 \((i,h_i,j,h_j)\) 來描述,表示若在第 \(i\) 場使用型號為 \(h_i\) 的車子,則第 \(j\) 場遊戲要使用型號為 \(h_j\) 的車子。

​ 你能幫小 l 選擇每場遊戲使用的賽車嗎?如果有多種方案,輸出任意一種方案。如果無解,輸出 「-1」(不含雙引號)。

\(n \le 50000,d \le 8,m\le100000.\)

話說我noi的題改起來好費力啊tat 一道就一天(還對著資料改)

不難發現這和之前一道題類似la 3713。

雖然有很多種類,但每個人也只有兩種可以選擇,並且關係也是二元的。

所以我們就可以套2-sat模板了qwq 不會2-sat請點這裡.

首先暴力列舉每個 \(x\) 的狀態,從 \(a,b,c\) 中選取乙個就行了。

然後對於那些二元關係 \((i,h_i,j,h_j)\),就如下考慮。

\(i\) 可以選擇 \(h_i\) 這種賽車

\(j\) 無法選擇 \(h_j\) 這種賽車,那麼 \(i\) 就必不能選 \(h_i\) 了,就連一條 \(h_i \to \lnot h_i\) 的邊(此處 \(\lnot h_i\) 表示 \(i\) 可以選擇的另一種賽車)

\(j\) 可以選擇 \(h_j\) 這種賽車,那麼就只要連 \(h_i \to h_j\) 的邊就好了

\(i\) 不可以選擇 \(h_i\) 這種賽車:那就直接跳過就行了。

然後記得要建逆否命題等價的另一條邊。

如果用dfs複雜度為 \(\theta(3^d nm)\),tarjan就是 \(\theta(3^d (n+m))\) 啦。

其實第二個tarjan複雜度已經足夠過了。。。但是能更優!

有這樣乙個結論:

如果乙個 \(x\) 已經考慮過 \(a,b\) 兩個狀態了,那麼我們就不用考慮為 \(c\) 的狀態。

這是為什麼呢?

因為 \((a,b)\) 和 \((b,c)\) 的兩種選擇你都已經考慮過了,那麼剩下一種 \((a,c)\) 你前面一定會在前面一種選過。(因為每個點只能從那三種中選擇一種賽車,如果另外兩種都不可行,剩下一種也不行了)

這樣我們就可以將複雜度降為 \(\theta(2^d(n+m))\) qwq

然而又有垃圾uoj hack資料 我判了一下快到0.8s的時候,直接輸出"-1"...才過 (卡常數真的噁心)

我一開始寫了個dfs的可以跑過85分.... 然而有人能用這個a掉 orz

#include #define for(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)

#define fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)

#define set(a, v) memset(a, v, sizeof(a))

using namespace std;

inline bool chkmin(int &a, int b)

inline bool chkmax(int &a, int b)

inline int read()

void file()

const int n = 100010;

char str[n];

int jump[n], len, last;

int m;

struct limit lt[n];

char opt[n][2];

struct two_sat

void add_edge(int u, int v)

void add(int x, int xv, int y, int yv) //(x,xv) -> (y,yv)

int sta[n], top;

bool dfs(int x)

bool solve() }}

return true;

}} t;

int n;

inline bool check()

if (!flag)

t.add(u, v1, u, v1 ^ 1);}}

return t.solve();

} inline void out()

void dfs(int pos) return ; }

opt[pos][0] = 'b'; opt[pos][1] = 'c'; str[pos] = 'a'; dfs(jump[pos]);

opt[pos][0] = 'a'; opt[pos][1] = 'c'; str[pos] = 'b'; dfs(jump[pos]);

} int main ()

else }

m = read();

for (i, 1, m)

dfs(last);

puts("-1");

return 0;

}

正解就用tarjan縮點就行咯qwq

#include #define for(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)

#define fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)

#define set(a, v) memset(a, v, sizeof(a))

using namespace std;

inline bool chkmin(int &a, int b)

inline bool chkmax(int &a, int b)

inline int read()

void file()

const int n = 200100;

char str[n];

int jump[n], len, last;

int m;

struct limit lt[n];

char opt[n][2];

struct two_sat

void add_edge(int u, int v)

void add(int x, int xv, int y, int yv) //(x,xv) -> (y,yv)

int sccno[n], scc_cnt;

int dfn[n], lowlink[n];

int sta[n], top, clk;

void tarjan(int u)

else if (!sccno[v]) chkmin(lowlink[u], dfn[v]);

}if (lowlink[u] == dfn[u]) }}

bool solve()

void out()

}} t;

int n;

int cnt = 0;

inline bool check()

if (!flag) t.add(u, v1, u, v1 ^ 1);}}

int res = t.solve();

return res;

} void dfs(int pos)

if (pos == len + 1) return ; }

opt[pos][0] = 'a'; opt[pos][1] = 'c'; str[pos] = 'b'; dfs(jump[pos]);

opt[pos][0] = 'b'; opt[pos][1] = 'c'; str[pos] = 'a'; dfs(jump[pos]);

} int main ()

else }

m = read();

for (i, 1, m)

dfs(last); puts("-1");

return 0;

}

UOJ 318 NOI2017 蔬菜 貪心

我怎麼越來越菜了。首先,對於乙個物品,我們將它拆成若干份 最後一天拆成兩份,乙份的個數為1 價值為 a s 另乙份的個數為 c 1 mod x,價值為 a。對於在 c 1 x 天以及以前,每天有乙份個數為 x,價值為 a 的物品。於是,用堆維護物品,每次取最大價值的,就可以在 o n 2 m log...

NOI2017 遊戲 解題報告

d 這麼小,你考慮直接對 d 個東西暴力 列舉 x 為 a 或 b c 就不用了,因為 a,b 已經包含 c 了,剩下的就是個 2 sat 問題了 但是你發現有個情況是,在若 a 即 b 時,如果 b 被 ban 了,那麼 a 也要被 ban 我們記錄一下被 ban 的點,然後在球方案的時候判一下 ...

題解 P3825 NOI2017 遊戲

dfs 2 sat被卡得好開心啊 這道題目乍一看是一道 3 sat 的題目,變數是每個地圖,選擇是車的型別。但要注意乙個事實 除了那d個地圖之外,其它的地圖事實上只有2種選擇。而對於那d個x型地圖,我們可以窮舉假設它是a型或b型,因為a型 b型的合法選擇的並還是x型,所以不影響答案。接下來就是連邊的...