CF538H Summer Dichotomy

Link
如果没有总人数的限制的话,两个班的人数分别为\(R=\min(r_i),L=\max(l_i)\)是最优的。
如果人数超限了就减少\(L\),如果人数不够就增加\(R\)
然后就是个简单的二分图染色判定问题了。

#include<cstdio>
#include<cctype>
#include<vector>
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}
using IO::read;
int min(int a,int b){return a<b? a:b;}
int max(int a,int b){return a>b? a:b;}
const int N=100007;
std::vector<int>e[N];int l[N],r[N],col[N];
int dfs(int u)
{
    for(int v:e[u]) if(!col[v]) {if(col[v]=3-col[u],!dfs(v)) return 0;} else if(col[u]==col[v]) return 0;
    return 1;
}
int main()
{
    int L=read(),R=read(),n=read(),m=read(),mn=1e9,mx=0;
    for(int i=1;i<=n;++i) mx=max(mx,l[i]=read()),mn=min(mn,r[i]=read());
    if(mn+mx<L) mx=L-mn; else if(mn+mx>R) mn=R-mx;
    if(mn<0||mx<0) return puts("IMPOSSIBLE"),0;
    for(int i=1;i<=n;++i)
    {
	int f1=l[i]<=mn&&mn<=r[i],f2=l[i]<=mx&&mx<=r[i];
	if(!f1&&!f2) return puts("IMPOSSIBLE"),0;
	if(f1&&!f2) col[i]=1;
	if(!f1&&f2) col[i]=2;
    }
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
    for(int i=1;i<=n;++i) if(col[i]&&!dfs(i)) return puts("IMPOSSIBLE"),0;
    for(int i=1;i<=n;++i) if(!col[i]) if(col[i]=1,!dfs(i)) return puts("IMPOSSIBLE"),0;
    puts("POSSIBLE"),printf("%d %d\n",mn,mx);
    for(int i=1;i<=n;++i) printf("%d",col[i]);
}
posted @ 2020-01-27 15:14  Shiina_Mashiro  阅读(321)  评论(0编辑  收藏  举报