前言
感觉不是很难。
虽然一开始想着是废掉的缩点。
仔细想想又没有这样实现的道理。
题意
n个人。
有m个按时间的暗杀行动。
第i次请杀手杀ai和bi,如果都活着杀手按照心情杀一个,都死了就不杀,只活一个杀死活的那个。
问m次暗杀过后有多少对人可能都存活?
题解
考虑按时间倒着来。
如果你想要x存活,每当遇到与x有关的,又会出现新的应该存活的。
我们称为存活集合。
每次一个两端均不在存活集合的无视,都在则集合内均不能存活,只有一端在那么另一端也加入集合。
如果x和y都要存活,显然x和y分别都有可能存活且存活集合交集为空(有交的话一定有一个被杀)。
那么就很容易了。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=400+10,maxm=100000+10;
int a[maxm],b[maxm];
bool bz[maxn][maxn],p[maxn],czy;
int i,j,k,l,r,t,x,y,n,m,ans;
int main(){
scanf("%d%d",&n,&m);
fo(i,1,m) scanf("%d%d",&a[i],&b[i]);
fo(i,1,n){
p[i]=1;
bz[i][i]=1;
fd(j,m,1){
x=a[j];y=b[j];
if (!bz[i][x]&&!bz[i][y]) continue;
if (bz[i][x]&&bz[i][y]){
p[i]=0;
break;
}
bz[i][x]=bz[i][y]=1;
}
}
fo(i,1,n-1)
fo(j,i+1,n)
if (p[i]&&p[j]){
czy=1;
fo(k,1,n)
if (bz[i][k]&&bz[j][k]){
czy=0;
break;
}
if (czy) ans++;
}
printf("%d\n",ans);
}