CF.1027F.Session in BSU(思路 并查集)

题目链接

\(Description\)

有\(n\)个人都要参加考试,每个人可以在\(ai\)或\(bi\)天考试,同一天不能有两个人考试。求最晚考试的人的时间最早能是多少。无解输出-1。

\(Solution\)

把每个人向\(ai,bi\)连边。对于每个连通块单独考虑。
记点数为n,边数为m。可以发现当某一连通块n>m(n=m+1)时,可以有一个点不选(最大的);
当n=m时,所有点都要选;n<m时,无解。
用并查集维护连通,顺便维护最大、次大值。当第一次出现环时,即n=m;第二次出现就无解(n<m)了。
离散化可以写个Hash省掉log。

怎么这种题还是不去想连边。。

//795ms 41500KB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
//#define MAXIN 200000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=2e6+5;

int ref[N],A[N>>1],B[N>>1],fa[N],mx[N],smx[N];
bool tag[N];
//char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline int Find(int x,int r)
{
    int l=1,mid;
    while(l<r)
        if(ref[mid=l+r>>1]<x) l=mid+1;
        else r=mid;
    return l;
}
inline int Getfa(int x)
{
    return x==fa[x]?x:fa[x]=Getfa(fa[x]);
}

int main()
{
    int n=read(),t=0;
    for(int i=1; i<=n; ++i) ref[++t]=A[i]=read(),ref[++t]=B[i]=read();
    std::sort(ref+1,ref+1+t); int cnt=1;
    for(int i=2; i<=t; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];

    for(int i=1; i<=cnt; ++i) fa[i]=i,mx[i]=ref[i];
    for(int i=1,x,y,r1,r2; i<=n; ++i)
    {
        x=Find(A[i],cnt), y=Find(B[i],cnt);
        if((r1=Getfa(x))!=(r2=Getfa(y)))
        {
            fa[r2]=r1, tag[r1]|=tag[r2];//!
            if(mx[r2]>mx[r1]) smx[r1]=std::max(mx[r1],smx[r2]), mx[r1]=mx[r2];
            else smx[r1]=std::max(smx[r1],mx[r2]);
        }
        else if(tag[r1]) return puts("-1"),0;
        else tag[r1]=1;
    }
    int ans=0;
    for(int i=1; i<=cnt; ++i)
        if(fa[i]==i)
            if(tag[i]) ans=std::max(ans,mx[i]);
            else ans=std::max(ans,smx[i]);
    printf("%d\n",ans);

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/9637658.html

时间: 2024-08-29 14:46:01

CF.1027F.Session in BSU(思路 并查集)的相关文章

CF 1027F Session in BSU (并查集+树上构造)

题目大意:你可以在第$ai$天或者第$bi$天进行第$i$场考试,每天最多进行一场考试,求把所有考试都考完的最早结束时间 由于天数可能很大,需要离散 把问题抽象成一棵树,每个点最多被"分配"一条边,现在要删点 画画图可以发现 如果一个联通块是一棵树,那么可以删去至多一个点 如果一个联通块是一个单环树(n个点n条边),那么一个点都不能删掉 如果一个联通块边数大于点数,会发现无法把每个点只分配一条边,不合法,输出-1 判树还是单环树,求一个联通块内点的度总和/2和点数比较即可 并查集维护一

CF 500 B. New Year Permutation 并查集

User ainta has a permutation p1, p2, ..., pn. As the New Year is coming, he wants to make his permutation as pretty as possible. Permutation a1, a2, ..., an is prettier than permutation b1, b2, ..., bn, if and only if there exists an integer k (1 ≤ k

cf 990G GCD Counting (莫比乌斯反演 并查集)

990G 给你一棵树,问你有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\),对于\(i\in [1,200000]\)输出点对数目. 这题没有做出来,主要还是莫比乌斯反演时间太长不熟悉了.同时统计点对的技巧也自己没有想出来,实在是不应该. 我们设\(h(i)\)是有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\)的倍数的答案.于是有\(h(i)=\sum_{i=1}^{\lflo

poj3667(并查集区间合并&amp;区间查询)

题目链接: http://poj.org/problem?id=3667 题意:第一行输入 n, m表示有 n 间房间(连成一排的), 接下来有 m 行输入, 对于接下来的 m 行输入: 1 x : 询问是否有长度为 x 的连号空房, 若有, 住进最左边并输出对应编号: 2 x y : 将区间 [x, x + y - 1] 的房间清空: 思路: 并查集区间合并&区间查询 下面一段题解摘自: http://www.cnblogs.com/scau20110726/archive/2013/05/0

HDU1198水管并查集Farm Irrigation

Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot of samll squares. Water pipes are placed in these squares. Different square has a different type of pipe. There are 11 types of pipes, which is marked

HDU 3635 Dragon Balls(并查集--路径压缩拓展应用)

题目大意: 初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中. 现在又2种操作: T A B,表示把A球所在城市全部的龙珠全部转移到B城市.(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动). Q A,表示查询A.要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0) 思路:并查集,难点在于求龙珠的转移次数,可以在路径压缩的过程中沿着递归路径累加. //Accepted 1740 KB 5

hdu 5176(并查集)

The Experience of Love Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 645    Accepted Submission(s): 216 Problem Description A girl named Gorwin and a boy named Vivin is a couple. They arrived

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可以利用这个性质 考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配 那么我们考虑把这个点点匹配的模型转化成点边匹配 我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了 而这个问题,我们显然可以用并查集来很好的解决 考虑