[codevs1069]关押罪犯 二分图染色

题目←

思路:
既然说不用并查集来贪……那二分答案吧Orz
然后就没有了
注意这里二分的是数组下标,L永远指向不可能值,而又因为冲突是可能不产生的,所以L初始应在-1上

代码:

#include
#include
#include
#include
using namespace std;
const int MAXN = 100000 + 50;
int head[MAXN],dis[MAXN << 1],next[MAXN << 1],tot;
int n,m;
struct edge{
    int f,t,v;
}l[MAXN],e[MAXN];
int col[MAXN];
queue <int> q;
void init(int n){
    tot = 0;
    for(int i = 1;i <= n;i ++){
        head[i] = -1,col[i] = -1;
    }
    while(!q.empty())q.pop();
}
void build(int f,int t,int v){
    l[++ tot] = (edge){f,t,v};
    next[tot] = head[f];
    head[f] = tot;
}
int L,R,mid;
bool cmp(edge a,edge b){
    return a.v < b.v;
}
bool flag = false;
void bfs(int x){
    q.push(x);
    col[x] = 1;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i = head[u];i != -1;i = next[i]){
            int t = l[i].t;
            if(col[t] == -1){
                col[t] = !col[u];
                q.push(t);
            }
            else if(col[t] == col[u]){
                flag = true;
                return;
            }
        }
    }
}
bool C(int mid){
    for(int i = mid + 1;i <= m;i ++){
        build(e[i].f,e[i].t,e[i].v);
        build(e[i].t,e[i].f,e[i].v);
    }
    flag = false;
    for(int i = 1;i <= n;i ++){
        if(col[i] == -1)bfs(i);
        if(flag)return false;
    }
    return true;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i ++){
        scanf("%d%d%d",&e[i].f,&e[i].t,&e[i].v);
    }
    sort(e + 1,e + m + 1,cmp);
    L = -1;R = m + 1;
    while(R - L > 1){
        mid = L + R >> 1;
        init(n);
        if(C(mid))R = mid;
        else L = mid;
    }
    printf("%d",e[R].v);
    return 0;
}

你可能感兴趣的:(二分,二分图)