2022/7/13 cf训练(二分图染色+二分)

区别于每日一题,此类文章书写的分析不如每日一题详细,难度也可能不如每日一题,重在保证每天的刷体量


E. Split Into Two Sets
题意:每张骨牌上有两个数字,分成两个集合,没证每个集合中骨牌上的数字只出现一次
思路:
1.保证每个数字都出现了2次,才可以继续做下去。
2.好久没做了,没想到是二分图染色问题。
3.需要转一个弯,本体无法通过骨牌进行染色,只能通过数字(范围在1~n)进行染色。
4.偶数环是可以区别分两个集合的,奇数环是无法满足题意的。(此处还有点疑惑)

#include<bits/stdc++.h>

using namespace std;
const int N=1e6+5;
int n,p[N],q[N];
vector<int>a[N];
bool flag;

int dfs(int x,int k)
{
    if(!q[x])
        q[x]=k;
    else
    {
        if(q[x]==k) return 1;
        else return 0;
    }
    for(int i=0;i<a[x].size();i++)
    {
        int now=a[x][i];
        if(!dfs(now,3-k))
            return 0;
    }
    return 1;
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            a[i].clear();
            p[i]=q[i]=0;
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            int x,y;cin>>x>>y;
            p[x]++,p[y]++;
            a[x].push_back(y),a[y].push_back(x);
        }
        for(int i=1;i<=n;i++)
            if(p[i]!=2)
            flag=1;
        for(int i=1;i<=n;i++)
        {
            if(!q[i])
            {
                if(!dfs(i,1))
                    flag=1;
            }
        }
        if(flag)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
}

C. Schedule Management
好久没写二分答案了,这题竟然第一反应是思维题。
题意:每个任务对应一个工人,对应的工人可在1个小时内完成,而其他工人完成此任务需要2个小时,问最少需要多少个小时。
思路:套用二分模板。明显需要将花费最多时间的工人,将其任务分配给其他工人。
1.每次枚举出一个时间,要求可完成所有任务。
2.凡是超过规定时间的工人任务分配给在规定时间以下完成的工人。注意时间的转化,需要除以2.
3.若满足返回1,继续二分答案;否则返回0,上调答案。

#include<bits/stdc++.h>

using namespace std;
const int N=1e6+5;
int n,m;
int a[N];
int check(int x)
{
    int res=0;
    for(int i=n;i>=1;i--)
    {
        if(a[i]>=x)
            res+=a[i]-x;
        else
        {
            res-=(x-a[i])/2;
            res=max(res,0);
        }
    }
    if(!res)    return 1;
    else    return 0;
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            a[i]=0;
        for(int i=1;i<=m;i++)
        {
            int x;cin>>x;
            a[x]++;
        }
        sort(a+1,a+n+1);
        int l=0,r=2*m,mid,ans;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid))
                r=mid-1,ans=mid;
            else
                l=mid+1;
        }
        cout<<ans<<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值