正题
题目大意
nnn个苹果,依次来mmm个人会在两个苹果(ui,vi)(u_i,v_i)(ui,vi)中选择一个吃(如果都没了就不吃了)
求有多少对苹果可以同时存活
解题思路
设gi,jg_{i,j}gi,j表示iii不吃时jjj是否必吃,我们从后到前枚举边,那么我们有转移gi,uj=gi,vj=gi,uj∣gi,vjg_{i,u_j}=g_{i,v_j}=g_{i,u_j}|g_{i,v_j}gi,uj=gi,vj=gi,uj∣gi,vj。
设fif_{i}fi表示iii是否必吃,对于枚举到的一条边,如果gi,uj和gu,vjg_{i,u_j}和g_{u,v_j}gi,uj和gu,vj都有的话,那么我们就有fi=1f_i=1fi=1。
然后计算答案即可
时间复杂度O(n3)O(n^3)O(n3)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510,M=5e5+10;;
int n,m,x[M],y[M],ans;
bool g[N][N],f[N];
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]);for(int i=1;i<=n;i++){g[i][i]=1;for(int j=m;j>=1;j--){if(g[i][x[j]]&&g[i][y[j]]){f[i]=1;break;}g[i][x[j]]=g[i][y[j]]=g[i][x[j]]|g[i][y[j]];}}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(f[i]||f[j])continue;bool flag=1;for(int k=1;k<=n;k++)if(g[i][k]&&g[j][k]){flag=0;break;}ans+=flag;}printf("%d",ans/2);
}