题意:每个人都有自己喜欢的一本或多本书,然后在这n个人中每个人可以借自己喜欢的书,求n个人中拿到自己喜欢的书的人的最大值。
思路:读完题应该就能想到是二分图的题目,直接套二分图的模板
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#define ll long long
#define lowbit(x) ((~x+1)&x)
using namespace std;
const int inf = 0x3f3f;
const int N = 2e4+10;
vector<int>g[N];
int n,m;
int mx[N],my[N];
int dx[N],dy[N];
int dis,vis[N];
bool sp() {
queue<int>q;
dis=inf;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0; i<n; i++) {
if(mx[i]==-1) {
q.push(i);
dx[i]=0;
}
}
while(!q.empty()) {
int u=q.front();
q.pop();
if(dx[u]>dis) break;
int sz=g[u].size();
for(int i=0; i<sz; i++) {
int v=g[u][i];
if(dy[v]==-1) {
dy[v]=dx[u]+1;
if(my[v]==-1) dis=dy[v];
else {
dx[my[v]]=dy[v]+1;
q.push(my[v]);
}
}
}
}
return dis!=inf;
}
bool dfs(int u) {
int sz=g[u].size();
for(int i=0; i<sz; i++) {
int v=g[u][i];
if(!vis[v]&&dy[v]==dx[u]+1) {
vis[v]=1;
if(my[v]!=-1&&dy[v]==dis) continue;
if(my[v]==-1||dfs(my[v])) {
my[v]=u;
mx[u]=v;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++) {
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
int ans=0;
memset(mx,-1,sizeof(mx));
memset(my,-1,sizeof(my));
while(sp()) {
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++) {
if(mx[i]==-1&&dfs(i)) ans++;
}
}
if(ans==n) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}