AtCoder Grand Contest 016 E - Poor Turkeys
阿新 • • 發佈:2018-12-24
是我 har 抉擇 urn inline pri tin mat void 擋槍子,但在這之前的時間,\(j\)需要收到和\(i\)一樣的保護。那麽這樣就會牽扯到一堆火雞,於是我們記\(S_i\)表示要留下\(i\),要為這一系列連鎖反應擋槍的火雞集合
題目傳送門:https://agc016.contest.atcoder.jp/tasks/agc016_e
題目大意:
有\(N\)只火雞,現有\(M\)個人,每個人指定了兩只火雞\(x,y\),每人依次進行操作,會從\(x,y\)中選一只火雞吃掉;如果只有一個,那麽必定吃掉剩下那個;如果都沒有,這個人只能餓著肚子離開了……
問最後有多少對火雞可能存活
考慮倒序,我們設狀態\(f_{i,j}\)表示如果要留下\(i\),那麽是否要燉了\(j\),初始狀態\(f_{i,i}=1\)
我們倒序考慮,如果\(f_{i,j}=1\),那麽必然存在某個時刻會在\(i,j\)中抉擇,這時\(j\)就會為了\(i\)
如果存在某個時刻,需要在\(x,y\)中選擇,但是存在\(f_{i,x}=f_{i,y}=1\),那麽\(i\)就無法存活,這是結論1
考慮一對雞\((i,j)\)如何被留下,如果存在一只雞\(x\),既要保護\(i\),也要保護\(j\),那麽\((i,j)\)必然不能共存,因為\(x\)只有一條命……因此我們可以得到,\((i,j)\)同時存在,當且僅當\(S_i\land S_j=\varnothing\),這是結論2
應用結論1和2即可,復雜度為\(O(nm+n^3)\),集合判交可以使用bitset優化
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int frd(){ int x=0,f=1; char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline int read(){ int x=0,f=1; char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=4e2,M=1e5; int A[M+10],B[M+10]; bool vis[N+10],sub[N+10][N+10]; int main(){ int n=read(),m=read(),Ans=0; for (int i=1;i<=m;i++) A[i]=read(),B[i]=read(); for (int i=1;i<=n;i++){ sub[i][i]=1; for (int j=m;j;j--){ bool x=sub[i][A[j]],y=sub[i][B[j]]; if (x&&y) vis[i]=1; else if (x) sub[i][B[j]]=1; else if (y) sub[i][A[j]]=1; } } for (int i=1;i<=n;i++){ if (vis[i]) continue; for (int j=i+1;j<=n;j++){ if (vis[j]) continue; bool flag=1; for (int k=1;k<=n;k++) if (sub[i][k]&&sub[j][k]) flag=0; Ans+=flag; } } printf("%d\n",Ans); return 0; }
AtCoder Grand Contest 016 E - Poor Turkeys