D170 二分图判定 二分+染色法 P1525 [NOIP 2010 提高组] 关押罪犯
D170 二分图 染色法+二分 P1525 [NOIP 2010 提高组] 关押罪犯_哔哩哔哩_bilibili
P1525 [NOIP 2010 提高组] 关押罪犯 - 洛谷
n 名罪犯,两个监狱,需要把怨气值大的两人分到两个监狱,求最小化每个监狱内的最大怨气值
思路
将罪犯看做点,仇恨关系看做无向边,边权是怨气值
将所有点分成两组,使得各组内的边权最大值尽可能小
考虑对怨气值二分答案,在 $[0,10^9]$ 之间枚举边权 mid
判断能否将所有点分成两组,使得所有权值大于 mid 的边都在组间,而不在组内
也就是判断由所有点以及所有权值大于 mid 的边能否构成二分图
样例,当 mid=3512 时,大于 mid 的三条边权的端点都被分在两个组,mid 就是所求答案

二分图判定,当然是染色法啦
复习:D24【模板】二分图判定 染色法 - 董晓 - 博客园
C123【模板】扩展域并查集 P1892 [BOI2003] 团伙 - 董晓 - 博客园
// 二分图 二分+染色法 O((n+m)*30) #include<bits/stdc++.h> using namespace std; const int N=20010; vector<pair<int,int> > e[N]; //邻接表 int n,m,color[N]; bool dfs(int u,int c,int mid){ color[u]=c; for(auto i:e[u]){ int v=i.first, w=i.second; if(w<=mid) continue; //只保留[mid+1,1e9]的边权 if(!color[v]){ if(dfs(v,3-c,mid)) return 1; //有奇环,返1 } else if(color[v]==c) return 1; //有奇环,返1 } return 0; //无奇环,返0 } bool check(int mid){ memset(color,0,sizeof color); for(int i=1; i<=n; i++) if(!color[i])if(dfs(i,1,mid)) return 0; //有奇环,返0 return 1; //无奇环,返1 } int main(){ scanf("%d%d",&n,&m); for(int a,b,c;m--;){ scanf("%d%d%d",&a,&b,&c); e[a].push_back({b,c}); e[b].push_back({a,c}); } int l=-1,r=1e9+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) r=mid; //无奇环,扩大可行区[r,1e9] else l=mid; } printf("%d\n",r); }
浙公网安备 33010602011771号