题意:可以录取x个学生,t<=x<=T。将学生分成两组,大小分别为n1,n2。一共有n个老师需要分进这两个组里,有m对老师互相讨厌不能同组,每个老师都对其所在组的大小有[li,ri]的限制。求一种学生和老师的合法分配方案。li,ri<=1e9,n,m<=1e5.
标程:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100005; 4 int t,T,n,m,c[N],n1,n2,l[N],r[N],x,y; 5 vector<int> vec[N]; 6 void fail(){puts("IMPOSSIBLE");exit(0);} 7 void dfs(int x,int col) 8 { 9 if (c[x]) 10 if (c[x]==col) return;else fail(); 11 c[x]=col; 12 for (int i=0;i<vec[x].size();i++) dfs(vec[x][i],3-col); 13 } 14 bool in(int i,int x) {return l[i]<=x&&x<=r[i];} 15 int main() 16 { 17 scanf("%d%d",&t,&T); 18 scanf("%d%d",&n,&m);n1=1e9; 19 for (int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]),n1=min(n1,r[i]),n2=max(n2,l[i]); 20 for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),vec[x].push_back(y),vec[y].push_back(x); 21 if (n1+n2<t) n2=t-n1; 22 else if (n1+n2>T) n1=T-n2; 23 if (n1<0||n2<0) fail(); 24 for (int i=1;i<=n;i++) 25 if (in(i,n1)) 26 { 27 if (!in(i,n2)) dfs(i,1); 28 }else if (in(i,n2)) dfs(i,2); 29 else fail(); 30 for (int i=1;i<=n;i++) if (!c[i]) dfs(i,1); 31 printf("POSSIBLE %d %d ",n1,n2); 32 for (int i=1;i<=n;i++) printf("%d",c[i]); 33 puts(""); 34 return 0; 35 }
题解:二分图染色
回忆一下分成两组有什么算法:匹配、染色、2-sat……
这里有不等式限制2-sat和匹配显然都不合适。
化简不等式:有n1或n2<=min(ri),max(li)<=n1或n2,可以证明n1,n2分别取两个限制不劣,设n1<=min(ri),max(li)<=n2。将这个限制和t<=n1+n2<=T的限制取交集。因而最后n1<=k1,n2>=k2,而如果有解k1,k2不变,故取n1=k1,n2=k2即可。
将老师的匹配区间根据n1和n2的限制二分图染色(厌恶连边),先确定只包含n1或n2的,再确定都包含的。