B. Balance of the Force
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
A long time ago in a galaxy far, far away, there was a group of knights who mastered the ancient power - the Force. To bring order and balance to the universe, the Force is divided into two categories that conflict with each other: the Jedi, who acts on the light side of the Force through non-attachment and arbitration, and the Sith, who uses the dark side through fear and aggression.
There were NN knights who mastered the Force. Each knight could join either the light side or the dark side. When joining the light side, the knight possesses LiLi Force; when joining the dark side, the knight possesses DiDi Force.
To maintain order and balance of the universe, the knights wanted to make the Force difference between the most powerful knight and the weakest knight as small as possible. To make things even tougher, some knights did not get along well, and they refused to join on the same side.
Input
The first line of the input gives the number of test cases, TT (1≤T≤201≤T≤20). TT test cases follow.
For each test case, the first line contains two integers NN (1≤N≤2×1051≤N≤2×105) and MM (0≤M≤2×1050≤M≤2×105), where NN is the number of knights and MM is the number of knight pairs that didn't get along well.
The next MM lines each contains two integers xx and yy (1≤x≠y≤N1≤x≠y≤N), describing knight xx and knight yy didn't get along well.
The following NN lines each contains two integers, LiLi and DiDi (1≤Li,Di≤1091≤Li,Di≤109), representing the Force when the knight joined the light side and the dark side.
Output
For each test case, output one line containing "Case x: y", where x is the test case number (starting from 11) and y is the minimum difference between the strongest knight and weakest knight, or "IMPOSSIBLE" (quotes for clarify) if it's impossible for the knights to pick side without violating the given constraints.
Example
input
Copy
3 3 1 1 2 1 2 3 4 5 6 4 3 1 2 2 3 1 3 1 2 3 4 5 6 7 8 2 0 2 1 3 5
output
Copy
Case 1: 3 Case 2: IMPOSSIBLE Case 3: 1
Note
For the case 1, let knight 1 join the dark side then let knight 2 and 3 join the light side, the power of each knight are 2, 3 and 5, and the answer should be 5−2=35−2=3.
For the case 3, let both knights join the light side, the answer becomes 3−2=13−2=1.
题意:给出n个人,总共两个阵营,约束有m对人不能出现在同意阵营。每个人都有加入不同阵营带来的不同能力值。问每个人选好阵营后,最大能力的减去最小能力的值的最小是多少。
题解:把约束分成若干个联通块,每个连通块会有两种值。记录每次最大值,排个序。从大到小遍历最大值。每次都用线段树维护最小值的最大,使得差值尽量小。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
#define lc d<<1
#define rc d<<1|1
#define mid ((l+r)>>1)
using namespace std;
#define ll long long
const int maxn=2e5+50;
vector <int> ve[maxn];
int tot, n, m, num;
int l[maxn], d[maxn], col[maxn], vis[maxn];
int maxx[maxn][5], minn[maxn][5];
struct zzh{
int mxva, miva, opmiva, id;
bool operator < (const zzh &t)const{
return mxva > t.mxva;
}
}mxst[maxn*2];
struct tree{
int mi;
tree(){}
tree(int mm):mi(mm){}
tree operator + (const tree &t){
return tree(min(t.mi, mi));
}
}T[maxn*4];
void init(){
memset(col, 0, sizeof(col));
memset(vis, 0, sizeof(vis));
memset(maxx, 0, sizeof(maxx));
memset(minn, 0x3f3f3f3f, sizeof(minn));
for(int i=1; i<=n; i++)
ve[i].clear();
tot = 0;
}
void pushup(int d){
T[d]=T[lc]+T[rc];
}
void build(int l, int r, int d){
if(l==r){
T[d].mi=max(minn[l][1], minn[l][2]);
return;
}
build(l, mid, d<<1);
build(mid+1, r, d<<1|1);
pushup(d);
}
void update(int l, int r, int d, int L, int x){
if(l==r){
T[d].mi = x;
return;
}
if(mid < L) update(mid+1, r, rc, L, x);
else update(l, mid, lc, L, x);
pushup(d);
return;
}
tree query(int l, int r, int d, int x){
if(l==r) return T[d];
if(mid < x) return query(mid+1, r, rc, x);
return query(l, mid, lc, x);
}
bool ff;
void dfs(int x, int color){
if(color==1){
maxx[tot][1]=max(maxx[tot][1], l[x]);
minn[tot][1]=min(minn[tot][1], d[x]);
maxx[tot][2]=max(maxx[tot][2], d[x]);
minn[tot][2]=min(minn[tot][2], l[x]);
}
else{
maxx[tot][1]=max(maxx[tot][1], d[x]);
minn[tot][1]=min(minn[tot][1], l[x]);
maxx[tot][2]=max(maxx[tot][2], l[x]);
minn[tot][2]=min(minn[tot][2], d[x]);
}
col[x]=color;
for(int i=0, y; i<ve[x].size(); i++){
y=ve[x][i];
if(col[y]==col[x]){
ff=1;
break;
}
if(!col[y]){
dfs(y, -color);
}
}
return ;
}
int main(){
int t;
scanf("%d",&t);
for(int o=1; o<=t; o++){
printf("Case %d: ",o);
init();
num=0;
scanf("%d%d",&n,&m);
for(int i=1, x, y; i<=m; i++){
scanf("%d%d",&x,&y);
ve[x].push_back(y);
ve[y].push_back(x);
}
ff = 0;
for(int i=1; i<=n; i++)
scanf("%d%d",&l[i], &d[i]);
for(int i=1; i<=n; i++) {
if(!col[i]) {
tot++;
dfs(i, 1);
if(ff) break;
mxst[++num].mxva=maxx[tot][1], mxst[num].miva=minn[tot][1], mxst[num].opmiva=minn[tot][2], mxst[num].id=tot;
mxst[++num].mxva=maxx[tot][2], mxst[num].miva=minn[tot][2], mxst[num].opmiva=minn[tot][1], mxst[num].id=tot;
}
}
if(ff){
puts("IMPOSSIBLE");
continue;
}
sort(mxst+1, mxst+1+num);
int ans = mxst[1].mxva;
build(1, tot, 1);
for(int i=1; i<=num; i++){
vis[mxst[i].id] ++;
update(1, tot, 1, mxst[i].id, mxst[i].opmiva);
ans = min(ans, mxst[i].mxva-T[1].mi);
if(vis[mxst[i].id]==2) break;
update(1, tot, 1, mxst[i].id, mxst[i].miva);
}
printf("%d\n",ans);
}
}