【codevs1069】关押罪犯

第一次做二分图染色qwq,用了一个下午qwq,看电脑看的我眼睛难受

这个题满足二分的性质,因此二分图+二分……

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct in
{
    int to,ne,co;
}ter[200020]; 
queue<int>qwq;
bool flag;
int n,m,t,x,l,r,y,z,tail,head[200020],col[20005],a[100005];
inline void build(int f,int l,int c)
{
    ter[++tail]=(in){l,head[f],c},head[f]=tail;
    ter[++tail]=(in){f,head[l],c},head[l]=tail;
}
inline void bfs(int xx,int qi)
{
    if(!flag)//如果之前发现当前答案不能满足则直接返回 
        return; 
    while(!qwq.empty())
        qwq.pop();
    qwq.push(qi);
    col[qi]=1;
    while(!qwq.empty())
    {
        int qaq=qwq.front();
        for(int i=head[qaq];i;i=ter[i].ne)
        {
            if(ter[i].co<=xx)//如果说这对犯人的怒气值小于当前答案,则说明他们可以被接受 
                continue;
            if(col[ter[i].to]>0)//如果现在找到的点之前被走过 
            {
                if(col[ter[i].to]==col[qaq])//且颜色与现在的队首颜色相同 
                {
                    flag=0;return;//当前答案不成立,返回 
                }
            }
            else//否则染色 
                col[ter[i].to]=3-col[qaq],qwq.push(ter[i].to);
        }
        qwq.pop();
    }
}
inline bool ask(int xia)
{
    int biao=a[xia];
    memset(col,-1,sizeof(col));
    flag=1;
    for(int i=1;i<=n;i++)
        if(col[i]<0)//如果这个点没有走过 
            bfs(biao,i);
    return flag;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&x,&y,&z),build(x,y,z),a[i+1]=z;
    a[1]=0;
    sort(a+1,a+2+m);//先排个序,便于下面二分 
    l=1,r=m+1;//l,r是数组下标 
    while(l<r)//二分答案 
    {
        int mid=l+r>>1;
        if(ask(mid))//如果返回值为真,则说明现在的答案太大,可以进一步缩小 
            r=mid;
        else//否则说明答案太小 
            l=mid+1;
    }
    printf("%d",a[l]);
}

 

posted @ 2017-10-20 17:22  那一抹落日的橙  阅读(208)  评论(0编辑  收藏  举报