zoukankan      html  css  js  c++  java
  • CF538H Summer Dichotomy

    一、题目

    点此看题

    二、解法

    ( t 2sat) 的做法就不讲了,线段树优化建图要写麻

    从另一个角度切入,我们可以先枚举每个小组中的学生人数,可以知道老师是否能分配到这个小组中,然后根据 (m) 个限制来对老师二分图染色即可。

    瓶颈在于枚举学生人数,先不考虑总人数的限制,发现最优的取值是 (n_1=min{r_i},n_2=max{l_i})

    • 如果 (n_1geq n_2),那么所有区间两两相交,这两个端点值最优。
    • 如果 (n_1<n_2),那么增大 (n_1) 会让某个老师无法选组,减少 (n_2) 也会让某个老师无法选组,而减少 (n_1) 只会让 (1) 组的覆盖范围更少,增大 (n_2) 同理,所以它们是最优的。

    如果 (n_1+n_2) 不符合总人数的限制怎么办?综合上面的讨论我们可以发现如果 (n_1+n_2<t) 那么我们增大 (n_2),如果 (n_1+n_2>t) 那么我们减小 (n_1),这样调整也是最优的。

    最后只需要验证这一组 ((n_1,n_2)) 是否能跑出二分图匹配即可,时间复杂度 (O(n))

    三、总结

    区间问题着重考虑端点,可以将需要枚举的东西用贪心来最优化。

    #include <cstdio>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    const int M = 100005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,a,b,n1,n2,l[M],r[M],c[M],vis[M];
    vector<int> g[M];
    void dfs(int u)
    {
    	vis[u]=1;
    	for(auto v:g[u])
    	{
    		if(c[v]==c[u])
    		{
    			puts("IMPOSSIBLE");
    			exit(0);
    		}
    		c[v]=3-c[u];
    		if(!vis[v]) dfs(v);
    	}
    }
    signed main()
    {
    	a=read();b=read();n=read();m=read();
    	n1=1e9;n2=0;
    	for(int i=1;i<=n;i++)
    	{
    		l[i]=read();r[i]=read();
    		n1=min(n1,r[i]);
    		n2=max(n2,l[i]);
    	}
    	if(n1+n2<a) n2=a-n1;
    	if(n1+n2>b) n1=b-n2;
    	if(n1<0 || n2<0)
    	{
    		puts("IMPOSSIBLE");
    		return 0;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		int f1=l[i]<=n1 && n1<=r[i];
    		int f2=l[i]<=n2 && n2<=r[i];
    		if(!f1 && !f2)
    		{
    			puts("IMPOSSIBLE");
    			return 0;
    		}
    		if(!f1) c[i]=2;
    		if(!f2) c[i]=1;
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int u=read(),v=read();
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	for(int i=1;i<=n;i++)
    		if(c[i] && !vis[i]) dfs(i);
    	for(int i=1;i<=n;i++)
    		if(!vis[i]) c[i]=1,dfs(i);
    	puts("POSSIBLE");
    	printf("%d %d
    ",n1,n2);
    	for(int i=1;i<=n;i++)
    		printf("%d",c[i]);
    }
    
  • 相关阅读:
    PHPCMS V9后台表单向导用户提交的信息新增“修改”的功能
    phpcms V9最实用的23个调用代码
    phpcms V9推荐位无法调用自定义字段的解决方法
    将博客搬至CSDN
    爬取淘宝商品信息selenium+pyquery+mongodb
    selenium库
    requests库+ajax数据分析+多线程爬取头条图集
    requests微博爬取Ajax数据+mongoDB存储
    redis存储
    pymongo操作MongoDB
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15223042.html
Copyright © 2011-2022 走看看