Gym 102055B Balance of the Force

https://blog.csdn.net/lalalafloat/article/details/103056764?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163635050916780255222938%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=163635050916780255222938&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_v2~rank_v29-8-103056764.pc_v2_rank_blog_default&utm_term=%E7%BA%BF%E6%AE%B5%E6%A0%91&spm=1018.2226.3001.4450

(二分图染色 + 联通块 + 线段树)

#include<bits/stdc++.h>
#define inf 1e18
#define ll long long 
#define int long long 
#define ull unsigned long long 
#define PI acos(-1.0)
#define PII pair<int,int>
#define lowbit(x) (x & (-x))
using namespace std;
const int N = 1e6+7, M = N * 4;
int x,y,n,m;
int b_vis[N];
int col[N];
int a[N][2],vis[N][2];
int h[N],nxt[M],e[M],idx;
struct node{
    int l,r;
    int v;
}tr[N*4];
void pushup(int u){
    tr[u].v=min(tr[u<<1].v,tr[u<<1|1].v);
}
void build(int u,int l,int r){
    tr[u]={l,r,(ll)inf};
    if(l==r)    return ;
    int mid = l+r >>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
}
//    modify(1,seg[i].id,seg[i].min);
void modify(int u,int x,int v){
    if(tr[u].l==tr[u].r){
        if(tr[u].v==inf)tr[u].v = v;
        else            tr[u].v = max(tr[u].v,v);
        return ;
    } 
    int mid = tr[u].l + tr[u].r >>1;
    if(x<=mid)    modify(u<<1,x,v);
    else        modify(u<<1|1,x,v);
    pushup(u);
}
struct bb{
    int min,max,id;
    bool operator < (const bb &rhs)const{
        return max < rhs.max;
    }
}seg[N<<1];
void add(int u,int v){
    e[++idx]=v;
    nxt[idx] = h[u];
    h[u] = idx;
}
bool dfs(int u,int c){
    col[u] = c;
    for(int i=h[u];i;i=nxt[i]){
        int v= e[i];
        if(col[v] == -1){
            if(!dfs(v,!c))    return false;
        }
        else if(col[v]==c)    return false;
    }
    return true;
}
void dfs2(int x,int c,int num){
    vis[x][c]=1;
    seg[num].min=min(seg[num].min,a[x][c]);
    seg[num].max=max(seg[num].max,a[x][c]);
    for(int i=h[x];i;i=nxt[i]){
        int v = e[i];
        if(vis[v][c^1])continue;
        dfs2(v,c^1,num);
    }
}
void solve(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i)h[i]=0;
    for(int i=1;i<=m;++i){
        scanf("%lld%lld",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;++i){
        scanf("%lld%lld",&a[i][0],&a[i][1]);
    }
    int block = 0;//联通块数 
    
    //染色 判断是否存在方案 
    int flag=true;
    for(int i=0;i<=n;++i)    col[i]=-1; 
    for(int i=1;i<=n;++i)
        if(col[i]==-1){
            if(dfs(i,0)==false)    flag=false;
            block++;
        }
    if(flag==false){//染色失败 
        printf("IMPOSSIBLE\n");
        return ;
    }
    //cout<<"ok\n";
    for(int i=1;i<=block*2;++i){//块信息清空 
        seg[i].max=0;seg[i].min=inf;
        b_vis[i]=0;
    } 
    int cnt = 0;
    for(int i=1;i<=n;++i)    vis[i][0]=0,vis[i][1]=0;//划块路径清空 
    for(int i=1;i<=n;++i){
        if(vis[i][0]==0){
            dfs2(i,0,++cnt);//划分块 
            dfs2(i,1,++cnt);
            seg[cnt-1].id=cnt/2;
            seg[cnt].id=cnt/2;
        } 
    }
    sort(seg+1,seg+1+cnt);
    build(1,1,block);
    int ans = inf;
    int b_cnt = 0;//更新时已用过的块 
    for(int i=1;i<=cnt;++i){
        if(b_vis[seg[i].id]==0){
            b_cnt++;
            b_vis[seg[i].id]=1;
        }
        //线段树修改
        modify(1,seg[i].id,seg[i].min);
        if(b_cnt==block)ans = min (ans,seg[i].max-tr[1].v); 
        //        cout<<seg[i].max<<"    ==   "<<tr[1].v<<"\n";
    }
    printf("%lld\n",ans);
}
signed main(){
    int t=1;
    scanf("%lld",&t);
    for(int _=1;_<=t;++_){
        printf("Case %lld: ",_);
        solve();
    }
    return 0;
}

 

posted @ 2021-11-08 13:49  PdrEam  阅读(26)  评论(0编辑  收藏  举报