zoukankan      html  css  js  c++  java
  • 雀士分组(二分图染色 + 二分)

    题目链接:

    http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/4532.html

    题目大意:

    sdut雀士联盟中有许多水平各异的职业雀士,现在为了参加即将举办的神仙杯麻将比赛,联盟决定将所有雀士分为两队(碰精队和杠精队)分开举行训练赛。为了方便分组,联盟对每一位选手进行了雀力评估,对第i个雀士的评估得分为Ai。联盟出于对于雀士的心态考虑决定将实力相近的雀士分为一组,即让max(碰精队max - 碰精队min, 杠精队max - 杠精队min) 的值 最小(其中碰精队max代表碰精队中最高那位的雀力数值,其他同理)。不过联盟中部分雀士由于打法原因和一些其他雀士关系恶劣,绝对不能分在一组之内。分组方案的结果可以使一组人的人数为 0。

    Input

    第一行一个N(1 <= N <= 100000)代表联盟中一共有N名雀士,雀士编号由1至N。 
    第二行输入N个整数Ai(1 <= Ai <= 100000000),代表第i名雀士雀力评估得分。 
    接下来输入1个整数M(0 <= M <= 100000),代表有M组雀士关系恶劣,不能分进同一组。 
    接下来输入M行x, y(1 <= x, y <= N),代表编号为x的和编号为y的雀士关系恶劣, 保证不会重复输入雀士关系。

    Output

    假如没有办法将所有的雀士分成两队,输出 “impossible”(输出不包括引号),否则输出最小的max(碰精队max - 碰精队min, 杠精队max - 杠精队min)。

    具体思路:

    首先对二分图进行染色,然后把每一组的最大值和最小值求出来。再求出整个区间的最大值和最小值。把点权放置在线段上进行处理,每一次二分答案,这个时候合法区间被分成了两组,

    然后判断当前两种不能放在一起的能不能分别放置在这两个区间中,注意单点的时候,这个需要特判。

    AC代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 # define ll long long
      4 # define inf 0x3f3f3f3f
      5 const int maxn = 2e5+100;
      6 const int  N = 15;
      7 const int mod = 1e9+7;
      8 int n;
      9 int a[maxn];
     10 int color[maxn];
     11 vector<int>Edge[maxn];
     12 int flag;
     13 void  dfs(int u,int type)
     14 {
     15     color[u]=type;
     16     for(int i=0; i<Edge[u].size(); i++)
     17     {
     18         int to=Edge[u][i];
     19         if(color[to]!=0&&color[to]==type)
     20             flag=1;
     21         if(color[to]!=0)
     22             continue;
     23         dfs(to,-type);
     24     }
     25 }
     26 struct node
     27 {
     28     pair<int,int>t1,t2;
     29 } q[maxn];
     30 map<int,int>vis;
     31 int sz[maxn];
     32 int minn=inf,maxx=0;
     33 int id=0;
     34 bool check(int mid)
     35 {
     36     for(int i=1; i<=id; i++)
     37     {
     38         if(sz[i]>=2)
     39         {
     40             if(q[i].t1.second<=minn+mid&&q[i].t2.first>=(maxx-mid))
     41                 continue;
     42             if(q[i].t2.second<=minn+mid&&q[i].t1.first>=(maxx-mid))
     43                 continue;
     44         }
     45         else if(sz[i]==1)
     46         {
     47             if(q[i].t1.first<=minn+mid||q[i].t1.first>=(maxx-mid))
     48                 continue;
     49         }
     50         return false;
     51     }
     52     return true;
     53 }
     54 int main()
     55 {
     56     scanf("%d",&n);
     57     for(int i=1; i<=n; i++)
     58     {
     59         scanf("%d",&a[i]);
     60         minn=min(minn,a[i]);
     61         maxx=max(maxx,a[i]);
     62     }
     63 //    cout<<minn<<" "<<maxx<<endl;
     64     int m,st,ed;
     65     scanf("%d",&m);
     66     for(int i=1; i<=m; i++)
     67     {
     68         scanf("%d %d",&st,&ed);
     69         Edge[st].push_back(ed);
     70         Edge[ed].push_back(st);
     71     }
     72     flag=0;
     73     for(int i=1; i<=n; i++)
     74     {
     75         if(color[i]!=0)
     76             continue;
     77         dfs(i,i);
     78         if(flag)
     79             break;
     80     }
     81     if(flag)
     82         printf("impossible
    ");
     83     else
     84     {
     85         for(int i=1; i<=n; i++)
     86         {
     87             q[i].t1=make_pair(1e9+1,0);
     88             q[i].t2=make_pair(1e9+1,0);
     89         }
     90         for(int i=1; i<=n; i++)
     91         {
     92             if(!vis[abs(color[i])])
     93                 vis[abs(color[i])]=++id;
     94             sz[vis[abs(color[i])]]++;
     95             if(color[i]>0)
     96             {
     97                 q[vis[abs(color[i])]].t1.first=min(q[vis[abs(color[i])]].t1.first,a[i]);
     98                 q[vis[abs(color[i])]].t1.second=max(q[vis[abs(color[i])]].t1.second,a[i]);
     99             }
    100             else
    101             {
    102                 q[vis[abs(color[i])]].t2.first=min(q[vis[abs(color[i])]].t2.first,a[i]);
    103                 q[vis[abs(color[i])]].t2.second=max(q[vis[abs(color[i])]].t2.second,a[i]);
    104             }
    105         }
    106         int l=0,r=maxx-minn;
    107         // cout<<l<<" "<<r<<endl;
    108         int ans=-1;
    109         while(l<=r)
    110         {
    111             int mid=l+r>>1;
    112             if(check(mid))
    113             {
    114                 ans=mid;
    115                 r=mid-1;
    116             }
    117             else
    118                 l=mid+1;
    119         }
    120         if(ans==-1)
    121             printf("impossible
    ");
    122         else
    123             printf("%d
    ",ans);
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    【C语言】用"I love you!"打印心形
    android js与控件交互初探。
    android 调用webview控件,为逆向h5app做准备
    git命令
    kdevelp 导入makefile工程
    解决vmvare关闭过慢
    用python.twisted.logfile每天记录日志,并用不记录stdout中的内容
    关于bjam编译自己模块出错的问题
    俄罗斯黑客在美国监狱中获刑4年,到底是什么原因?
    美国的电信巨头T-Mobile今天披露了另一起数据遭黑客泄露事件
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10968781.html
Copyright © 2011-2022 走看看