洛谷P1525 关押罪犯(二分图+二分法+思维)

题目链接:https://www.luogu.com.cn/problem/P1525

题目解法:这个题很不错,是个思维题。因为换个问法就是,题目要求你问二分图同组内最大2点间花费。那么其实一个很不错的想法就是二分框定mid,我们保证大于mid的边能构建成二分图。这个时候就需要去找所谓mid的封顶值了。因为符合线性增大原理,所以可以二分来解决找mid。大概整体意思就是一般图里面扣最大二分图吧。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
int tot,head[maxn];
struct E{
    int to,next,w;
}edge[maxn<<1];
void add(int u,int v,int w){
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int n,m;
bool bfs(int mid){
    queue<int> q;int col[maxn]={0};
    rep(i,1,n){
        if(!col[i]){
            q.push(i);col[i]=1;
            while(!q.empty()){
                int now=q.front();q.pop();
                for(int i=head[now];i!=-1;i=edge[i].next){
                    int v=edge[i].to,w=edge[i].w;
                    if(w>=mid){
                        if(!col[v]){
                            col[v]=3-col[now];
                            q.push(v);
                        }
                        else if(col[v]==col[now]){
                            return false;
                        }
                    }
                }
            }
        }
    }
    return true;
}
int main(){
    cin>>n>>m;mem(head,-1);
    int L=0,R=0;
    rep(i,1,m){
        int u,v,w;cin>>u>>v>>w;
        R=max(R,w);
        add(u,v,w);add(v,u,w);
    }
    while(R>L){
        int mid=(L+R)>>1;
        if(bfs(mid)) R=mid;
        else L=mid+1;
    }
    if(L-1>=0)cout<<L-1<<endl;
    else puts("0");
}
View Code

 

posted @ 2020-07-18 15:59  Anonytt  阅读(146)  评论(0编辑  收藏  举报