事前知識:
質問の意味簡単に言えば:
最大独立集合を求める図の二部グラフ。
最大点は点の同じ側の二組のそれぞれの大きさではないように、点の集合:二部グラフは、最大独立集合を意味します。
あなたはこれとことがわかります二部グラフの最大マッチングがリンクしているようです。
与えられたアイデンティティ:
図の点部グラフの最大独立集合= - =最小頂点カバー図ポイント - 最大マッチング。
最小頂点カバー手段:各エッジはその時点で少なくとも1つのエンドポイントの焦点を有するように、点の最小セット。
あなたは、その最小のカバレッジと最大のマッチポイントの本質は違いを見つけることでしょう。あなたは、側面には共通の側のポイントは、サイトの選択は、それぞれの側を少しああを満たすためにということです満たして選択しないでください。
だから、再び最大マッチングを求めて、次に何をすることができます引きます。
- ディテール
ハンガリーテンプレートアルゴリズムはからのようです(1 \)\〜\(N- \) (タイトルはそれは言うものの、再び生きることができるスイープ(0 \)\〜- 1 \)\(nは、しかし、この問題はできません)。だから、我々は考慮する必要があります\(0 \)、そして私たちが持っているに\(\ {テキストVIS} \ ) と\(\ {テキストマット} \ ) 割り当てられた\(--1 \) 。
時間の複雑さ:\(O(N \タイムズメートル)\) 。
実際のスコア:\(100のPTS \) 。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+1;
inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int n,m,T,vis[N],mat[N];
vector<int>G[N]; bool h[N];
inline bool dfs(int dep,int bs) {
if(vis[dep]==bs) return 0;
vis[dep]=bs;
for(int i=0;i<G[dep].size();i++) {
int x=G[dep][i];
if(mat[x]==-1 || dfs(mat[x],bs)) {
mat[x]=dep;
return 1;
}
} return 0;
}
int main(){
n=read(),T=read();
while(T--) {
int x=read(),y=read();
G[x].push_back(y);
} int ans=0;
memset(mat,-1,sizeof(mat));
memset(vis,-1,sizeof(vis));
for(int i=0;i<n;i++)
if(dfs(i,i)) ++ans;
printf("%d\n",n-ans);
return 0;
}