D174 二分图最大匹配 匈牙利算法 CF104427B Lawyers

D174 二分图最大匹配 匈牙利算法 CF104427B Lawyers_哔哩哔哩_bilibili

 

Problem - CF104427B Lawyers - Codeforces

有 𝑛 个律师,都被指控有欺诈罪.他们需要互相辩护,确保每一名律师都被释放.这 𝑛 个律师有 𝑚 个信任关系,一个信任关系 (𝑎,𝑏) 表示 𝑎 可以为 𝑏 辩护.任何一个受到辩护的律师都会被无罪释放,除了一个例外:如果 𝑎 和 𝑏 互相辩护,他们都会被判有罪.求是否可以使得每一名律师都被释放.

思路

对于信任关系 $(a,b)$ 不能直接从 $a$ 向 $b$ 连边,这样做,不能排除互相辩护的两条边

可以把信任关系 $(a,b)$ 看做一个无序对,即 $(a,b)$ 和 $(b,a)$ 映射为同一个点 $cnt$

对于关系 $(a,b)$ 和 $(b,a)$,从 $b$ 和 $a$ 都向这个点 $cnt$ 连边,选择时就只能选一条边

最终把 n 个律师看做 n 个左部点,m 个关系映射为 $cnt$ 个右部点,跑二分图最大匹配

如图,用 map 把 $(2,1)$ 和 $(1,2)$ 映射为点 1,匹配时可以排除互相辩护的两条边

注意:本题的数据范围 $2\times 10^5$,必须加优化

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

 

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

const int N=200005;
map<pair<int,int>,int> mp;
vector<int> e[N];
int n,m,ans,cnt;
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(){
  ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
  cin>>n>>m;
  for(int i=1,u,v; i<=m; i++){
    cin>>u>>v;
    if(mp[{u,v}]==0) mp[{u,v}]=mp[{v,u}]=++cnt;
    e[v].push_back(mp[{u,v}]);
  }
  
  for(int i=1; i<=n; i++){vis=0; if(dfs(i))ans++;}
  
  cout<<(ans==n?"YES":"NO")<<'\n';
  return 0;
}

 

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

const int N=200005;
map<pair<int,int>,int> mp;
vector<int> e[N];
int n,m,t,ans,cnt;
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(){
  ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
  cin>>n>>m;
  for(int i=1,u,v; i<=m; i++){
    cin>>u>>v;
    if(mp[{u,v}]==0) mp[{u,v}]=mp[{v,u}]=++cnt;
    e[v].push_back(mp[{u,v}]);
  }
for(int i=t=1; i<=n; i++,t++)if(dfs(i))ans++;
cout
<<(ans==n?"YES":"NO")<<'\n'; return 0; }

 

posted @ 2026-05-29 11:18  董晓  阅读(70)  评论(0)    收藏  举报