1. 程式人生 > >2018.10.11【BZOJ1143】【CTSC2008】祭祀river(最長反鏈)

2018.10.11【BZOJ1143】【CTSC2008】祭祀river(最長反鏈)

傳送門

解析:

DilworthDilworth定理: 最長反鏈長度==最小鏈覆蓋數。

證明我覺得VfleakingVfleaking部落格寫得很好%%%%%%%%%%%%%%%%%

程式碼:

#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; }