D175 二分图最大匹配 匈牙利算法 P1640 [SCOI2010] 连续攻击游戏

D175 二分图最大匹配 匈牙利算法 P1640 [SCOI2010] 连续攻击游戏_哔哩哔哩_bilibili

 

P1640 [SCOI2010] 连续攻击游戏 - 洛谷

给定 n 个装备,每个装备有两个属性值,每种装备只能使用其中一个属性,并且每个装备只能用一次。现在要从属性 1 开始连续增加,问最多能使用多少个装备(即属性值断档就终止)。

思路

显然需要从小到大枚举属性值,每个装备两个属性值只能用一个,这些提示我们

把属性值看做左部点,把装备看做右部点,从左向右对应连边

然后跑二分图最大匹配,一旦配对失败,即不能连续攻击就中断

注意:本题的数据范围 $10^6$,必须加优化

参考:D171【模板】二分图最大匹配 匈牙利算法 P2756 飞行员配对方案问题 - 董晓 - 博客园

// 二分图 匈牙利算法 O(V*E) 优化去掉 memset
#include<bits/stdc++.h>
using namespace std;

#define N 1000010
vector<int> e[10010];
int n,ans;
int match[N];
bitset<N> vis; //各二进制位清空很快

bool dfs(int u){
  for(auto v:e[u]){
    if(vis[v]) continue; //若女生v已参与当前轮试配,就跳过
    vis[v]=1; //记录女生v参与当前轮试配
    if(!match[v] || dfs(match[v])){ //若v没有男友 或 v的男友可以配她人
      match[v]=u; //记录v的男友是u
      return 1;   //返回配对成功
    }
  }
  return 0; //返回配对失败
}
int main(){
  scanf("%d",&n);
  for(int i=1,v; i<=n; i++)for(int j=0; j<2; j++)
    scanf("%d",&v),e[v].push_back(i);
  
  for(int i=1; i<=10000; i++){
    vis=0;
    if(dfs(i)) ans++;
    else break; //不能连续攻击就中断
  }
  
  printf("%d\n",ans);
  return 0;
}
 

 

// 二分图 匈牙利算法 O(V*E) 优化去掉 memset
#include<bits/stdc++.h>
using namespace std;

#define N 1000010
vector<int> e[10010];
int n,t,ans;
int vis[N],match[N];

bool dfs(int u){
  for(auto v:e[u]){
    if(vis[v]==t) continue; //若女生v已参与第t轮试配,就跳过
    vis[v]=t; //记录女生v参与第t轮试配
    if(!match[v] || dfs(match[v])){ //若v没有男友 或 v的男友可以配她人
      match[v]=u; //记录v的男友是u
      return 1;   //返回配对成功
    }
  }
  return 0; //返回配对失败
}
int main(){
  scanf("%d",&n);
  for(int i=1,v; i<=n; i++)for(int j=0; j<2; j++)
    scanf("%d",&v),e[v].push_back(i);
  
  for(int i=t=1; i<=10000; i++,t++){
    if(dfs(i)) ans++;
    else break; //不能连续攻击就中断
  }
  
  printf("%d\n",ans);
  return 0;
}

 

posted @ 2026-05-29 16:09  董晓  阅读(46)  评论(0)    收藏  举报