1. 程式人生 > >【題解】Atcoder AGC#16 E-Poor Turkeys

【題解】Atcoder AGC#16 E-Poor Turkeys

導致 存在 memset 沖突 -- ret main 不同 一個人

  %拜!顏神怒A此題,像我這樣的渣渣只能看看題解度日╭(╯^╰)╮在這裏把兩種做法都記錄一下吧~

  題解做法:可以考慮單獨的一只雞 u 能否存活。首先我們將 u 加入到集合S。然後我們按照時間倒序往回推,如果在時間 t 的時候發現有 u 和 v 同時被抉擇,為了保證 u 的存活我們只能殺掉 v,也就是說在 t - 1的時刻 v 必須存活。這時我們將 v 加入到集合 S 中,再繼續進行這個過程。如果在某個時刻我們發現 u 和 v 同時被抉擇,可 u 和 v 都已經在集合中出現過了(要求在這個時刻一並存活),這樣顯然是非法的。所以可以判定 u 沒有存活的可能。

  如果一只雞 u 能夠存活,我們把這個過程中獲得的 S 集合稱作 \(S_{u}\) 。u 和 v 能夠共存的充要條件即為 u 和 v 均有存活的可能,且 \(S_{u}\) 和 \(S_{v}\) 兩個集合不存在交集。為什麽呢?因為一只雞在 t 時刻出現在了 S 集合中,說明它將在 t 時刻被殺掉。如果兩個集合中 x 出現的時間不同,那麽出現了沖突;但它們又不可能在同一個時間出現,因為一個時間節點只有唯一的一個抉擇,反推回去也必然都是一樣的,但開始的節點一個是 u,一個是 v,所以不可能。得證。

  代碼:

#include <bits/stdc++.h>
using namespace std;
#define maxn 405
#define maxm 100500
int n, m, x[maxm], y[maxm], mark[maxn];
int ans, S[maxn][maxn];

int read()
{
    int x = 0, k = 1;
    char c; c = getchar();
    while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); }
    
while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * k; } int main() { n = read(), m = read(); for(int i = 1; i <= m; i ++) x[i] = read(), y[i] = read(); for(int i = 1; i <= n; i ++) { memset(mark, 0, sizeof(mark)); mark[i]
= 1; S[i][++ S[i][0]] = i; for(int j = m; j >= 1; j --) { if(mark[x[j]] && mark[y[j]]) { S[i][0] = -1; break; } if(mark[x[j]]) mark[y[j]] = 1; else if(mark[y[j]]) mark[x[j]] = 1; } if(S[i][0] == -1) continue; for(int j = 1; j <= n; j ++) if(mark[j]) S[i][0] ++, S[i][S[i][0]] = j; } for(int i = 1; i <= n; i ++) for(int j = i + 1; j <= n; j ++) { if(S[i][0] == -1 || S[j][0] == -1) continue; memset(mark, 0, sizeof(mark)); bool flag = 1; for(int k = 1; k <= S[i][0]; k ++) mark[S[i][k]] = 1; for(int k = 1; k <= S[j][0]; k ++) if(mark[S[j][k]]) { flag = 0; break; } if(flag) ans ++; } printf("%d\n", ans); return 0; }

  下面是顏神的解法(並沒有代碼...)也非常的妙,而且復雜度比題解還低……可以考慮建出一張圖,在這張圖上面所有有連邊的雞均無法共存來獲得答案。那麽如何建出這張圖?一個人選擇了 u 和 v 這兩只雞,那麽這兩只雞是一定不可能共存的。假設我們在 t - 1 時刻建出的圖滿足在 t - 1 時刻及之前出現的所有抉擇所限制不能共存的雞均有連邊,那麽考慮加入t時刻的抉擇之後會對這張圖產生什麽影響。

  考慮 u 和 v 的抉擇,會使哪些原本可以和 u 共存的雞不能再和 u 共存?如果圖中的一只雞 x 與 u 沒有連邊,也與 v 沒有連邊,那麽它與 u 的生死無關;如果一只雞 x 與 v 有連邊,而與 u 沒有連邊,說明 u 和 x 不能共存,我們添加一條從 u 到 x 的邊。因為 x 與 v 不能共存,所以若 x 存活,v 一定死亡。那麽新的 u,v 邊一定會導致 u 的死亡;若 x 死亡,那麽 u 可能依然存活,也可能已經死亡;但在這兩種情況下,x 都不能與 u 共存。對於 v 我們也是一樣的添邊。

  最後檢查一下哪些節點是可以共存的即可。

【題解】Atcoder AGC#16 E-Poor Turkeys