洛谷1525 关押罪犯(并查集)(黑白染色)

版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/82957662

题目

洛谷1525关押罪犯

题解1

贪心+扩展域并查集
把怨气值排序,大的当然要分配到两个不同的监狱。
一个点拆成两个点,分两层,不同监狱连不同层。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20010,maxm=100010;

int n,m;
int fa[maxn*2];

struct U{int x,y,c;}a[maxm];
bool cmp(U u1,U u2)
{
    return u1.c>u2.c;
}

int find_fa(int x)
{
    if(x==fa[x]) return x;
    return find_fa(fa[x]);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n*2;i++) fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);
    }
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        fa[find_fa(a[i].x)]=find_fa(a[i].y+n);
        fa[find_fa(a[i].x+n)]=find_fa(a[i].y);
        if(find_fa(a[i].x)==find_fa(a[i].y))
        {
            printf("%d\n",a[i].c);
            return 0;
        }
    }
    printf("0\n");
    return 0;
}

题解2

二分+黑白染色
答案显然满足二分性,问题转变成判断是否存在一种分配方案,使得所有大于mid的怨气值的人被分在不同监狱。
删掉所有边权小于等于mid的边,然后做黑白染色。如果染色中不发生冲突,那么这个mid可行。
黑白染色就好像在说,与我连边(怨气值大于mid)的人都不能和我有一样的颜色(监狱)。
这是利用了黑白染色可以判断是否是二分图的特点。其原理是判断是否有奇环,如果一张图有一个奇环,那么所有的点都存在与某个奇环。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20010,maxm=100010;
int n,m;

struct E{int y,c,next;}e[maxm<<1];int len=0,last[maxn];
void ins(int x,int y,int c)
{
    e[++len]=(E){y,c,last[x]};last[x]=len;
}

int c[maxn];
bool dfs(int x,int color,int mid)
{
    c[x]=color;
    for(int k=last[x];k;k=e[k].next)
    {
        int y=e[k].y;
        if(e[k].c<=mid) continue;
        if(c[y] && c[y]==color) return false;
        else if(!c[y])
            if(!dfs(y,3-color,mid)) return false;
    }
    return true;
}

bool check(int mid)
{
    memset(c,0,sizeof(c));
    for(int i=1;i<=n;i++)//debug 枚举所有
        if(c[i]==0)
            if(!dfs(i,1,mid)) return false;
    return true;
}

int main()
{
    int mxc=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,c;
        scanf("%d%d%d",&x,&y,&c);
        ins(x,y,c);ins(y,x,c);
        mxc=max(mxc,c);
    }
    
    int l=0,r=mxc,ans;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/82957662
今日推荐