P1525 关押罪犯 - 二分+二分图染色||并查集
传送门
一.二分+二分图染色
最小的最大,考虑二分。
每次二分影响值,将影响值不小于mid的两个人关进不同的监狱,即染成不同的颜色,分到二分图的两个不同的集合中。若最终形成的图是二分图,说明这种分法可行,影响值还有变小的可能;否则影响值只能更大。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20000+100,M=100000+100;
int n,m;
struct node{
int to,nxt;
long long w;
}e[M<<1];
int head[N],tot;
void add(int u,int v,long long w){
e[++tot]=(node){v,head[u],w};
head[u]=tot;
}
struct ed{
int u,v;
long long w;
}E[M];
int col[N];
bool dfs(int u,int c,long long mid){
col[u]=c;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].w>=mid){
if(col[v]==col[u]) return false;
if(!col[v]&&!dfs(v,3-c,mid)) return false;
}
}
return true;
}
bool check(long long mid){
for(int i=1;i<=n;i++) col[i]=0;
//不必重新建图,只保留边权>mid的即可
for(int i=1;i<=n;i++) if(!col[i]) if(!dfs(i,1,mid)) return false;
return true;
}
int main(){
scanf("%d%d",&n,&m);
long long l=0,r=-(1<<30);
for(int i=1;i<=m;i++){
int u,v;
long long w;
scanf("%d%d%lld",&u,&v,&w);
int c=u;
u=min(u,v);v=max(c,v);
add(u,v,w);add(v,u,w);
E[i]=(ed){u,v,w};
r=max(r,w);
}
r++;//扩大边界,防止漏解
while(l+1<r){
long long mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid;
}
printf("%lld",l);
return 0;
}二.并查集
贪心地想,将每对罪犯按影响值从大到小进行排序,每次将两个罪犯分到两个监狱中,直到出现冲突的情况,输出答案。
我们可以通过并查集来维护两个集合并查询集合所属关系。对于每个罪犯i,集合fa[i]表示在监狱1,集合fa[i+n]表示在监狱2。若出现两个罪犯在同一监狱的情况,说明出现了冲突,此时这对罪犯的影响值就是最小的影响值即为答案。最后注意特判没有冲突的情况。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20000+100,M=100000+100;
struct node{
int u,v;
long long w;
}e[M];
bool cmp(node a,node b){
return a.w>b.w;
}
int fa[N<<1];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
long long w;
scanf("%d%d%lld",&u,&v,&w);
e[i]=(node){u,v,w};
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=(n<<1);i++) fa[i]=i;
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v;
int fu=find(u),fv=find(v);
if(fu==fv){
printf("%lld",e[i].w);
return 0;
}
else {
fa[fu]=find(v+n);
fa[fv]=find(u+n);
}
}
printf("0");
return 0;
}<br /> 相关推荐
computermaths 2020-06-01
田有朋 2020-04-30
Cypress 2020-04-08
lickylin 2020-02-22
waitwolf 2019-11-09
yishujixiaoxiao 2019-11-03
hanyujianke 2019-10-21
鱼天翱 2019-06-27
vczh的日常 2018-05-25
BitTigerio 2018-04-16
心理学哲学批判性思维 2018-03-28
友心人 2018-03-21
BitTigerio 2018-03-19
ScalersTalk成长会 2018-03-05
ScalersTalk成长会 2018-03-05
HomoEconomicus 2018-02-17
SimonSsAlgo 2018-02-03
迷思 2018-01-11