SSL1341 Asteroids【二分图匹配】【匈牙利算法】

在这里插入图片描述
这道题运用的算法和SSL1338 人员分配【二分图匹配】一样,关键是你怎么样建图!
我们可以思考一个问题:怎样让一颗子弹直接把一行或一列打掉呢?
这时我们考虑匹配的性质,当一个点与另一个点匹配,那么这个点就不能再和其他点匹配(暂时)。
会发现,我们可以直接建图,行放在上,列放在下,当枚举到 i i i 点时,产生匹配,
其他所有点都不能与之匹配,相当于把其他边全部断掉(暂时),这就符合了一颗子弹直接把一行或一列打掉的情况。
所以最大匹配就是答案

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

int v[1000010],ls[1000010],link[1000010];
int n,k,x,y,tot,ans;

struct node
{
    
    
	int y,next;
}a[1000010];
void add(int x,int y)
{
    
    
	a[++tot].y=y;
	a[tot].next=ls[x];
	ls[x]=tot;
}
int dfs(int x)
{
    
    
	for(int i=ls[x]; i; i=a[i].next)
	 {
    
    
	 	int y=a[i].y;
	 	if(v[y]==0)
	 	 {
    
    
	 	 	v[y]=1;
	 	 	int fa=link[y];
	 	 	link[y]=x;
	 	 	if(fa==0||dfs(fa))
	 	 	  return 1;
	 	 	link[y]=fa;
	 	 }
	 }
	return 0;
}
int main()
{
    
    
    cin>>n>>k;
    for(int i=1; i<=k; i++)
     {
    
    
     	scanf("%d%d",&x,&y);
     	add(x,y);
     }
    for(int i=1; i<=n; i++)
     {
    
    
     	memset(v,0,sizeof(v));
     	dfs(i);
     }
    for(int i=1; i<=n; i++)  //要循环,不然就会出错
     if(link[i]!=0)
       ans++;
    cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/108150191
今日推荐