問題描述
何老闆養了n只雞(編號1到n)。何老闆打算從今天開始,連續m晚都喫雞。
每晚,何老闆會選一對指定編號的雞出來。若兩隻雞都活着,那麼他會隨便喫掉其中一隻;若只有一隻活着,另一隻之前已經被吃了,就喫還活着那隻;若兩隻雞都已被喫掉了,當晚就不喫雞。
何老闆想知道,m天后,可能有多少對雞同時活着?請你幫他算一算。(如果一對雞存活的概率>0,我們認爲他們可能活着)
輸入格式
第一行,兩個整數n和m
接下來m行,每行兩個整數x和y,第i行表示第i天選出的兩隻雞的編號。
輸出格式
一行,一個整數,表示最後還存活的雞的對數。
我們來分析一下第雞能夠存活下來的條件。
假設與第雞配對的雞按照順序分別爲
在與中,要存活,那麼就要被喫
在與中,要存活,那麼就要被喫
…
在與中,要存活,那麼就要被喫。
也就是說,如果某隻雞要存活下來,那麼與它配對的所有其他雞都要被喫。
所以我們設立一個狀態,表示第只要存活下來,第只雞必須活着等着爲犧牲被喫。
那麼第只雞不能存活的條件呢?
假設第只雞與第只雞配對了,並且
也就是說要存貨下來,那麼和都要存活下來,但是只能存活下來一個,於是在這種情況下第只雞必死。
接下來討論求解,也就是哪些對雞可以存活。
我們假設這對雞爲。
那麼這對雞的存活條件爲如果存在,那麼
時間複雜度:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
#define res(i,x) for(ll i=head[x];i;i=nxt[i])
using namespace std;
const ll N=405;
const ll M=1e5+5;
const ll Inf=1e18;
const ll Mod=1e9+7;
const db Eps=1e-10;
ll n,m,ans,a[M],b[M],flg[N],liv[N][N];
inline ll read() {
ll x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
int main() {
n=read(),m=read();
rep(i,1,m) a[i]=read(),b[i]=read();
rep(i,1,n) {
liv[i][i]=1;
red(j,m,1) {
ll fa=liv[i][a[j]],fb=liv[i][b[j]];
if(fa&&fb) {
flg[i]=1;break;
} else {
if(fa) liv[i][b[j]]=1;
if(fb) liv[i][a[j]]=1;
}
}
}
rep(i,1,n) if(!flg[i]) rep(j,i+1,n) if(!flg[j]) {
ll flag=1;
rep(k,1,n) if(liv[i][k]&&liv[j][k]) {
flag=0;break ;
}
if(flag) ans++;
}
printf("%lld\n",ans);
return 0;
}