[AGC016E] Poor Turkeys

太妙了!!


首先枚举每一只鸡,维护一个存活集合,初始化只有这只鸡。倒着考虑每一步。

  • 若两只鸡都没必要存活,就忽略
  • 若其中一只鸡需要存活,则另一只鸡也必须活到这一步,所以把另一只鸡也加入存活集合
  • 若两只鸡都必须存活,但是肯定有一只鸡要死,所以枚举的这只鸡必死

对于两只鸡,如果它们的存活集合包含了同一只鸡,显然这只鸡只能当一次替死鬼。所以若两只鸡的存活集合没有交集,则答案加一。


\(O(nm+n^3)\)

#include<bits/stdc++.h>
using namespace std;
 
template<typename T>
inline void Read(T &n){
    char ch; bool flag=false;
    while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
    for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
    if(flag)n=-n;
}

enum{
	MAXN = 405,
	MAXM = 100005
};

char scapegoat[MAXN][MAXN], dead[MAXN];
int n, m;

struct road{int u, v;}e[MAXM];

int main(){
	Read(n); Read(m);
	for(register int i=1; i<=m; i++) Read(e[i].u), Read(e[i].v);
	for(register int i=1; i<=n; i++){
		scapegoat[i][i] = true;
		for(register int j=m; j; j--){
			int u = e[j].u, v = e[j].v;
			if(scapegoat[i][u] and scapegoat[i][v]){
				dead[i] = true;
				break;
			}
			if(scapegoat[i][u]) scapegoat[i][v] = true;
			else if(scapegoat[i][v]) scapegoat[i][u] = true;
		}
	}
	int ans=0;
	for(register int i=1; i<=n; i++) if(not dead[i]) 
		for(register int j=i+1; j<=n; j++) if(not dead[j]) 
			for(register int k=1; k<=n; k++){
				if(scapegoat[i][k] and scapegoat[j][k]) break;
				if(k==n) ans++;
			}
	cout<<ans<<endl;
	return 0;
}
posted @ 2021-06-26 13:41  oisdoaiu  阅读(38)  评论(0编辑  收藏  举报