题面

传送门

思路

真是一道神奇的题目呢

题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配

注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分

那么我们可以利用这个性质

考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配

那么我们考虑把这个点点匹配的模型转化成点边匹配

我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了

而这个问题,我们显然可以用并查集来很好的解决

考虑一个联通块,如果联通块中边数大于点数,那么可以直接输出-1,因为此时边代表的是原题中需要满足的那个东西(考试),而边比点多就一定无解了

如果边数等于点数,那么显然这个联通块中做出最大值贡献的点应该是编号最大的那个。这种情况下我们会得到一棵基环树,每个边恰好有一个点和它匹配

如果边数小于点数,那么这个联通块肯定是一个树,那么此时对答案的贡献就是联通块中的次大值了,因为可以以最大值为根,不选根,剩下的每个点匹配连接它和它父亲的那条边

用并查集维护联通块内部的点数、边数、最大值和次大值,最后扫一遍,取所有联通块的最大贡献的最大值即可

Code

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cassert>
#define ll long long
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int f[2000010],maxn[2000010],sec[2000010],cnte[2000010],cntn[2000010];
inline int find(int x){return ((f[x]==x)?x:f[x]=find(f[x]));}
inline void join(int x,int y){
x=find(x);y=find(y);
if(x==y){
cnte[x]++;return;//注意这里也需要加一条边
}
f[x]=y;cnte[y]+=cnte[x]+1;cntn[y]+=cntn[x];
int tmp[4];
tmp[0]=maxn[x];tmp[1]=sec[x];tmp[2]=maxn[y];tmp[3]=sec[y];
sort(tmp,tmp+4);
maxn[y]=tmp[3];sec[y]=tmp[2];
}
struct node{
int val,num,pos;
}a[2000010];
int n,cnt;
inline bool cmp1(node l,node r){
return l.val<r.val;
}
inline bool cmp2(node l,node r){
return l.num<r.num;
}
int main(){
n=read();int i,j;
for(i=1;i<=n;i++) a[i].val=read(),a[i+n].val=read(),a[i].num=i,a[i+n].num=i+n;
sort(a+1,a+(n<<1)+1,cmp1);
for(i=1;i<=(n<<1);i++){
j=i;
while(a[i+1].val==a[i].val&&i<(n<<1)) i++;
cnt++;f[cnt]=cnt;cnte[cnt]=0;cntn[cnt]=1;maxn[cnt]=a[i].val;sec[cnt]=0;
while(j<=i) a[j].pos=cnt,j++;
}
sort(a+1,a+(n<<1)+1,cmp2);
for(i=1;i<=n;i++){
join(a[i].pos,a[i+n].pos);
}
int ans=0;
for(i=1;i<=cnt;i++){
if(f[i]==i){
if(cnte[i]>cntn[i]){
puts("-1");return 0;
}
if(cnte[i]==cntn[i]) ans=max(ans,maxn[i]);
if(cnte[i]<cntn[i]) ans=max(ans,sec[i]);
}
}
cout<<ans<<'\n';
}

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]的更多相关文章

  1. CF 1027 F. Session in BSU

    F. Session in BSU https://codeforces.com/contest/1027/problem/F 题意: n场考试,每场可以安排在第ai天或者第bi天,问n场考完最少需要 ...

  2. cf1027F. Session in BSU(并查集 匈牙利)

    题意 题目链接 $n$个人,每个人可以在第$a_i$天或第$b_i$,一天最多考一场试,问在最优的情况下,最晚什么时候结束 Sol 自己只能想到暴力匈牙利二分图匹配,然而还是被构造数据卡了.. 标算很 ...

  3. CF1027F Session in BSU (并查集+树上构造)

    题目大意:你可以在第$ai$天或者第$bi$天进行第$i$场考试,每天最多进行一场考试,求把所有考试都考完的最早结束时间 由于天数可能很大,需要离散 把问题抽象成一棵树,每个点最多被"分配& ...

  4. Codeforces 1027F Session in BSU - 并查集

    题目传送门 传送门I 传送门II 传送门III 题目大意 有$n​$门科目有考试,第$i​$门科目有两场考试,时间分别在$a_i, b_i\ \ (a_i < b_i)​$,要求每门科目至少参加 ...

  5. codeforces 659F F. Polycarp and Hay(并查集+bfs)

    题目链接: F. Polycarp and Hay time limit per test 4 seconds memory limit per test 512 megabytes input st ...

  6. 线段树、最短路径、最小生成树、并查集、二分图匹配、最近公共祖先--C++模板

    线段树(区间修改,区间和): #include <cstdio> #include <iostream> #include <cstring> using name ...

  7. HD2444The Accomodation of Students(并查集判断二分图+匹配)

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  8. codeforces #541 F Asya And Kittens(并查集+输出路径)

    F. Asya And Kittens Asya loves animals very much. Recently, she purchased nn kittens, enumerated the ...

  9. F. Asya And Kittens 并查集维护链表

    reference :https://www.cnblogs.com/ZERO-/p/10426473.html

随机推荐

  1. Python线程创建与使用

    Python多为线程编程提供了两个简单明了的模块:thread和threading,Python3中已经不存thread模块,已经被改名为_thread,实际优先使用 threading模块. 1.P ...

  2. datatable行内内容太长,有时不自动换行解决方法

    加一个css属性即可 style = "word-wrap:break-word;" js代码: "render": function (data, type, ...

  3. datatable常用设置

    bSort: false, // 是否排序功能 bFilter: false, // 过滤功能 bPaginate: true, // 翻页功能 bInfo: true, // 页脚信息 bProce ...

  4. Nagios 监控Windows服务器(详细篇)

    1. 监控内容 windows服务器的内部参数包括以下 a. 内存使用状况 b. CPU负载 c. 磁盘使用状况 d. 服务状态 e. 运行的进程 2. 监控原理 在windows服务器内安装NSCl ...

  5. 用ajax获取淘宝关键字接口

    可定需要查看淘宝界面的结构,按F12查看网页,此时先清除一下网页中的数据,让Network制空,随后在输入框中输入新的内容,比如钱包,数据中会出现新的数据.点击及查看蓝色方框中的内容 点击之后,你可以 ...

  6. python__系统 : socket_TCP相关

    tcp和udp对比起来.还是tcp相对稳定一些,但是因为有三次挥手和四次握手,以及确认包(ack)的存在,可能在速度上会比udp慢. 用python的socket模块可以建立tcp服务端: from ...

  7. json_encode 的小技巧

    做了一个 API 文档自动生成,解析的是每个 控制器类 的注释 json 数据,在做测试工具的时候,多层的 json 只有通过一个 textarea 把数据弄进去.如下图 怎么格式化 Json 数据并 ...

  8. [CQOI2007]余数求和 (分块+数学

    题目描述 给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如G(10, 5)=5 ...

  9. 汉罗塔问题——Python

    汉罗塔问题就是一个循环的过程:* (有两种情况) 如果被移动盘只有一个盘子,可以直接移动到目的盘 但是被移动盘有多个盘子,就先需要将上面的n-1个盘子通过目的盘移动到辅助盘,然后将被移动盘最下面一个盘 ...

  10. 使用perl发邮件

    如果你使用的是 window 系统,没有 sendmail 工具.这时你就可以使用 perl 的 MIME:Lite 模块作为邮件客户端来发送邮件. 这里我们直接用 cpan 来安装(需要 root ...