D175 二分图最大匹配 匈牙利算法 P1640 [SCOI2010] 连续攻击游戏
D175 二分图最大匹配 匈牙利算法 P1640 [SCOI2010] 连续攻击游戏_哔哩哔哩_bilibili
给定 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; }
浙公网安备 33010602011771号