原题
题目大意
给你一个集合的大小
N
,
然后有一些限制:
集合里的数范围是
集合中的数
mod5=0,1,2,3,4
的数的个数各为
N/5
。
还有
q
个附加限制,就是元素值为
问是否存在一个集合满足条件。
范围
(5 ≤ n ≤ b ≤ 104,1 ≤ q ≤ 104)
解题思路
我们不妨加一个限制就是元素值为
[1,b]
的个数为
n
。这样,我们的限制就可以描述集合了。先按限制的
然后就可以使用网络流了, (S,mod0,n/5) , (S,mod1,n/5) , (S,mod2,n/5) , (S,mod3,n/5) , (S,mod4,n/5) ,表示 mod 不同值的个数都是 n/5 , (i,T,quantityi−quantityi−1) ,还有就是把每个区间的对5取模的个数求出来连边就行了。
参考程序
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 10055
#define cannot() puts("unfair")
#define can() puts("fair")
#define oo 1e9
using namespace std;
int n,b,q,S,T;
int head[maxn],t[maxn*20],next[maxn*20],v[maxn*20],sum;
int tmp[10];
struct note{
int up,num;
}a[maxn];
bool cmp(note i,note j){
return i.up<j.up||i.up==j.up && i.num<j.num;
}
void ins(int x,int y,int z){
t[++sum]=y;
v[sum]=z;
next[sum]=head[x];
head[x]=sum;
}
void insert(int x,int y,int z){
ins(x,y,z);
ins(y,x,0);
}
int vh[maxn],dis[maxn],di[maxn],his[maxn],pre[maxn],ans;
void sap(){
int tp=T;
bool p;
vh[0]=tp+1;
int x=S;
int aug=oo;
while (dis[S]<tp){
p=0;
his[x]=aug;
for(int i=di[x];i;i=next[i]){
if (v[i]&&dis[t[i]]+1==dis[x]){
p=1;
di[x]=i;
pre[t[i]]=x;
aug=min(aug,v[i]);
x=t[i];
if (x==T){
ans+=aug;
while (x!=S){
int tmp=x;
x=pre[x];
v[di[x]]-=aug;
v[di[x] ^ 1]+=aug;
}
aug=oo;
}
break;
}
}
if (!p){
int k,min;
min=tp+1;
for(int i=head[x];i;i=next[i]){
if (v[i]&&min>dis[t[i]]){
min=dis[t[i]];
k=i;
}
}
--vh[dis[x]];
if (vh[dis[x]]==0) break;
vh[++min]++;
dis[x]=min;
di[x]=k;
if (x!=S){
x=pre[x];
aug=his[x];
}
}
}
}
int main(){
sum=1;
scanf("%d%d%d",&n,&b,&q);
fo(i,1,q) scanf("%d%d",&a[i].up,&a[i].num);
a[++q].up=b;
a[q].num=n;
sort(a+1,a+q+1,cmp);
fo(i,2,q){
if (a[i].up==a[i-1].up&&a[i].num!=a[i-1].num){
cannot();
return 0;
}
if (a[i].up>a[i-1].up&&a[i].num<a[i-1].num){
cannot();
return 0;
}
}
S=0;
T=q+1;
fo(i,1,q){
if (i>1) tmp[0]=a[i].num-a[i-1].num;
else tmp[0]=a[i].num;
int down;
if (i>1) down=a[i-1].up;
else down=0;
insert(S,i,tmp[0]);
fo(j,0,4) tmp[j]=a[i].up / 5;
fo(j,0,a[i].up % 5) tmp[j]++;
fo(j,0,4) tmp[j]-=down/5;
fo(j,0,down % 5) tmp[j]--;
fo(j,0,4) insert(i,T+j,tmp[j]);
}
fo(i,0,4) insert(T+i,T+5,n / 5);
T+=5;
sap();
if (ans==n) can();
else cannot();
return 0;
}