Educational Codeforces Round 49 (Rated for Div. 2) F. Session in BSU

本文介绍了一种算法,用于解决如何在多个可选考试日期中为多项考试安排最优时间的问题,目标是最小化完成所有考试所需的总时间。通过构建连通图并分析不同节点类型之间的关系,该算法能够确定是否存在可行的解决方案,并计算出完成所有考试的最早可能日期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F. Session in BSU
time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Polycarp studies in Berland State University. Soon he will have to take his exam. He has to pass exactly
n
exams.

For the each exam
i
there are known two days:
a
i
— day of the first opportunity to pass the exam,
b
i
— day of the second opportunity to pass the exam (
a
i
<
b
i
). Polycarp can pass at most one exam during each day. For each exam Polycarp chooses by himself which day he will pass this exam. He has to pass all the
n
exams.

Polycarp wants to pass all the exams as soon as possible. Print the minimum index of day by which Polycarp can pass all the
n
exams, or print -1 if he cannot pass all the exams at all.

Input
The first line of the input contains one integer
n
(
1

n

10
6
) — the number of exams.

The next
n
lines contain two integers each:
a
i
and
b
i
(
1

a
i
<
b
i

10
9
), where
a
i
is the number of day of the first passing the
i
-th exam and
b
i
is the number of day of the second passing the
i
-th exam.

Output
If Polycarp cannot pass all the
n
exams, print -1. Otherwise print the minimum index of day by which Polycarp can do that.

Examples
inputCopy
2
1 5
1 7
outputCopy
5
inputCopy
3
5 13
1 5
1 7
outputCopy
7
inputCopy
3
10 40
40 80
10 80
outputCopy
80
inputCopy
3
99 100
99 100
99 100
outputCopy
-1
题意:有n个测试,每个测试可以有两个考试时间可以选择,如果想尽快把所有考试考完,问最少需要的时间;
做法:因为每个测试只有两个选择,那么可以把测试和时间连接起来,然后会的的一些连通图,设联通图里面为测试的点为a类点,为考试时间的点为b类点,那么在一个连通图里面b类点的个数小于等于a类点个数+1,因为最开始只有一个a类点,两个b类点,加入有一个a类点被连接进来,那么它所连接的两个点,最多只有一个点没有在当前的连通图里。
可知连通图里没有环,每个a类点旁边必定是b类点,如果b类点比a类点多一个,那么可以把这个图里面最大的那个b类点抠出来,剩下的点必定可以得到a类点和b类点的匹配。
如果b类点的个数等于a类点,那么必定是所有点相连。
如果b类点的个数小于a类点,明显是无解的。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
int a[N],b[N];
map<int,int> mp;
int fa[N*3];
int Find(int x){return x==fa[x]?x:fa[x] = Find(fa[x]); }
int cnt[N];
int mx[N],mx2[N];
int num[N*3];
int main(){
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++) scanf("%d %d",&a[i],&b[i]);
    for(int i = 1;i <= n;i ++){
        mp[a[i]] = 1;
        mp[b[i]] = 1;
    }
    int tot = 0;
    for(auto &iter: mp){
        tot++;
        num[n+tot] = iter.first;
        iter.second = n+tot;

    }
    for(int i = 1;i <= n+tot;i ++) fa[i] =i;
    for(int i = 1;i <= n;i ++){
        int f1 = Find(i);
        int f2 = Find(mp[a[i]]);
        if(f1 != f2){
            fa[f2] = f1;
        }
        int f3 = Find(mp[b[i]]);
        if(f1 != f3){
            fa[f3] = f1;
        }
    }
    memset(mx,-1,sizeof(mx));
    memset(mx2,-1,sizeof(mx2));
    for(int i = 1;i <= n+tot;i ++){

        int ff = Find(i);
        //if(i > n){cout <<"!!!" << i << ' '<< num[i] << ' ' <<ff <<' '<<mx[ff] << ' '<<mx2[ff] << endl;}
        if(i <= n) cnt[ff]++;
        else {
            cnt[ff]--;
            if(mx[ff] == -1 || num[i] > mx[ff]){
                mx2[ff] = mx[ff];
                mx[ff] = num[i];
            }
            else if(mx2[ff] == -1 || num[i] > mx2[ff]){
                mx2[ff] = num[i];
            }
        }
    }
    bool ans = true;
    int ret = 0;
    for(int i = 1;i <= n;i ++){
        //cout << i << ' '<< fa[i] << ' '<< cnt[i] << ' '<< mx[i]<< ' '<<mx2[i] << endl;
        if(fa[i] == i){
            if(cnt[i]> 0) ans = false;
            if(cnt[i] == 0){
                ret = max(ret,mx[i]);
            }
            if(cnt[i] < 0){
                ret = max(ret,mx2[i]);
            }
        }
    }
    if(ans){
        printf("%d\n",ret);
    }
    else puts("-1");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值