Asteroids POJ - 3041 匈牙利算法+最小点覆盖König定理

题意: 给出一个N*N的地图N   地图里面有K个障碍     你每次可以选择一条直线 消除这条直线上的所有障碍  (直线只能和列和行平行) 

问最少要消除几次

题解: 如果(x,y)上有一个障碍 则把X加入点集 V1 、Y加入点集V2   并且X Y连一条边  这样构成一个新图

如果选择 V1中的点 X 那么就相当于消去 (X,y)中的所有Y    要找使最小点覆盖 那就是跑一遍 匈牙利就行了 详细证明见二分图最小点覆盖König定理

其中 x y需要连单向边 不然会造成混乱 因为x=1 y=1是不同的含义

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1000;
 6 int n,k;
 7 int mp[maxn][maxn];
 8 int girl[maxn];
 9 int used[maxn];
10 bool find(int x){
11     int i,j;
12     for(j=1;j<=n;j++){
13         if(mp[x][j]==1&&used[j]==0){
14             used[j]=1;
15             if(girl[j]==0||find(girl[j])){
16                 girl[j]=x;
17                 return 1;
18             }
19         }
20     }
21     return 0;
22 }
23 int main(){
24     cin>>n>>k;
25     for(int i=1;i<=k;i++){
26         int a,b;
27         scanf("%d%d",&a,&b);//建边
28         mp[a][b]=1;
29     }
30     int sum=0;
31     for(int i=1;i<=n;i++){
32         memset(used,0,sizeof(used));//每次要初始化 因为used是用于判断之前有没有用过 什么叫之前有没用用过  比如进入3的递归,used[2]=1,3 和2匹配  2已经在之前已经有归属了  现在要进行拆边 find(girl(j))  此时假设girl(j)=5,5就不能和2匹配了,因为现在进行拆边操作时逻辑上已经认定 上层递归的used[2]=1 已经用了2
33         if(find(i))sum++;
34     }
35 cout<<sum<<endl;
36     return 0;
37 }

 

全部评论

相关推荐

10-25 12:05
已编辑
湖南科技大学 Java
若梦难了:我有你这简历,已经大厂乱杀了
点赞 评论 收藏
分享
11-15 19:28
已编辑
蚌埠坦克学院 硬件开发
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务