"蔚来杯"2022牛客暑期多校训练营10
E: Reviewer Assignment
题意:有m篇论文和n个审稿人,给出每个审稿人能审的论文集合,要求每个审稿人都要审一篇论文,让你将m篇论文分给n个审稿人,并且要让每个论文都给尽量多的审稿人看。
题解:匈牙利算法,遍历每篇论文,将每篇论文分配给一个可以审这篇论文的 审稿人,总共有n个审稿人,那就重复n次循环,但是若 当前已经没有审稿人能审了,则退出循环即可。
#include <iostream>
#include <cstring>
using namespace std;
struct node{
int to,nxt;
}edge[200000];//需要注意 总共最多有400*400=160000条边
int head[500];
int cnt=0;
int match[500];//存储 当前审稿人审那篇论文
bool st[500];
void add(int u,int v){
//链式前向星存图
edge[++cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
bool find(int x){
for(int i=head[x];i;i=edge[i].nxt){
int j=edge[i].to;
if(!st[j]){
st[j]=1;
if(match[j]==0||find(match[j])){
match[j]=x;
return true;
}
}
}
return false;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0 ; i<n; i++){
string str;
cin>>str;
for(int j=0;j<m;j++){
if(str[j]=='1'){
add(j+1,i+1);//若当前审稿人可以审读 此论文,则建边
}
}
}
int t=0;
for(int i=1;i<=n;i++){
//最多重复n次,为每篇论文找尽可能多的审稿人
bool flag=0;
for(int j=1;j<=m;j++){
memset(st,false,sizeof st);
if(find(j)){
//若当前论文能找到一个新的审稿人
t++;//又有一个新的审稿人获得了一篇论文
flag=1;
}
}
if(!flag)break;//若所有论文都找不到新的审稿人了,则没有必要循环了
}
if(t==n)<