2018.10.11【BZOJ1143】【CTSC2008】祭祀river(最長反鏈)
阿新 • • 發佈:2018-12-14
傳送門
解析:
有定理: 最長反鏈長度最小鏈覆蓋數。
證明我覺得的部落格寫得很好%%%%%%%%%%%%%%%%%
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=101;
int n,m;
bool g[N][N];
int match[N];
bool vis[N];
inline bool find(int u){
for(int re v=1;v<=n;++v){
if(g[u][v]&&!vis[v]){
vis[v]=true;
if(match[v] ==-1||find(match[v])){
match[v]=u;
return true;
}
}
}
return false;
}
signed main(){
n=getint(),m=getint();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint();
g[u][v]=1;
}
for(int re k=1;k<=n;++k)
for(int re i=1;i<=n;++i)
if(i!=k)for(int re j=1;j<=n;++j)
g[i] [j]=g[i][j]||(g[i][k]&&g[k][j]);
for(int re i=1;i<=n;++i)g[i][i]=0;
int ans=0;
memset(match,-1,sizeof match);
for(int re i=1;i<=n;++i){
memset(vis,0,sizeof vis);
if(find(i))++ans;
}
cout<<n-ans;
return 0;
}