【noip 2010】關押罪犯

去題面的傳送門

Solution 1:擴展域並查集

QAQ之前做過並的查集做法。
按權值排序,優先把大權值的分開
對於一個節點a,a+n表示和它不在一個監獄裏
代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

const int maxn1=20000+50,maxn2=100000+50;
int n,m,ans=0;
int fa[maxn1*2];
int cnt[maxn1*2];
struct hh
{
    int a,b,c;
}e[maxn2];

bool cmp(hh x,hh y)
{
    return x.c>y.c;
}
int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
} 
int main()
{
    memset(fa,0,sizeof(fa));
    scanf("%d%d",&n,&m);
    int N=n*2;
    for(int i=1;i<=N;++i) 
       fa[i]=i;
    for(int i=1;i<=m;++i) 
       scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
    sort(e+1,e+m+1,cmp);
    int k=0;
    for(int i=1;i<=m;++i)
    {
        int f1=find(e[i].a);
        int f2=find(e[i].b);
        if(f1!=f2) 
        {
            fa[f1]=find(e[i].b + n);
            fa[f2]=find(e[i].a + n);
        }
        if(f1==f2 && k==0) 
        {
            ans=e[i].c;
            k=1;
        }
    }
    printf("%d",ans);
    return 0;
}

Solution 2:二分答案+二分圖染色

這個也不難。
二分答案,只要權值大於這個答案的,都染爲不同的顏色,看是否能夠完成染色。這裏注意權值小於答案的,我們暫時不作處理(QAQ一開始因爲這個wa了),因爲它無論是分開還是不分開,都對答案沒有影響,所以順其自然染色,如果強行染色,會對後面的染色產生影響

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn=20000+10;
int n,cnt,ans,m,tot;
int fist[maxn],nxt[maxn*10],c[maxn*5],color[maxn];
bool vis[maxn];
struct hh
{
    int f,t,v;
}e[maxn*10];
queue<int>q;

void build(int f,int t,int v)
{
    e[++cnt]=(hh){f,t,v};
    nxt[cnt]=fist[f];
    fist[f]=cnt;
} 
bool done(int ds,int x)
{
    q.push(ds);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=fist[u];i!=-1;i=nxt[i])
        {
            int v=e[i].t;
            if(e[i].v>x)
            {
                if(!vis[v])
                {
                    color[v]=color[u]^1;
                    vis[v]=true;
                    q.push(v);
                    cnt++;
                }
                else if(color[v]==color[u]) return false;
            }

        }
    }
    return true;
}
bool check(int x)
{
    while(!q.empty()) q.pop();
    memset(vis,0,sizeof(vis));
    memset(color,0,sizeof(color));
    tot=0;
    for(int i=1;i<=n;++i)
    {
        if(!vis[i])
        {
            color[i]=1;
            vis[i]=true;
            tot++;
            if(!done(i,x)) return false;
        }
        if(tot==n) break;
    }
    return true;
}
int main()
{
    memset(fist,-1,sizeof(fist));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int a,b;
        scanf("%d%d%d",&a,&b,&c[i]);
        build(a,b,c[i]);
        build(b,a,c[i]);
    }
    sort(c+1,c+m+1);
    int l=0,r=m+1;
    while(l+1<r)
    {
        int mid=(l+r)>>1;
        if(check(c[mid])) r=mid;
        else l=mid;
    }
    if(check(c[l])) ans=c[l];
    else ans=c[r];
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章