CF 1027 F. Session in BSU

F. Session in BSU

https://codeforces.com/contest/1027/problem/F

题意:

  n场考试,每场可以安排在第ai天或者第bi天,问n场考完最少需要多少天。

 

分析:

  将所有的a与b连边,一条边相当于一场考试,一个点相当于一个考试时间,每条边需要找一个点。

  那么在一个联通块中,边数>点数,无解(这些考试都只能在这个联通块内的点考)。

  如果边数=点数,那么相当于出现了环,每条边和一个点匹配,即n场考试,n个考试时间,所以这个联通块内的答案就是最大的点。

  如果边数<点数,那么一定是一棵树,那么所有的最大的时间点就可以不选了,这个联通块内的答案就是次大值。

  并查集维护加边,与当期联通块的情况。加入一个条边,合并两个联通块,对新联通块维护最大值和次大值。

 

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 
19 const int N = 2000005;
20 
21 struct Node{
22     int a,b;
23 }A[N >> 1];
24 int Num[N], fa[N], fir[N], sec[N], tag[N];
25 
26 int find(int x) {
27     return x == fa[x] ? x : fa[x] = find(fa[x]);
28 }
29 int main() {
30     int n = read(), cnt = 0;
31     for (int i=1; i<=n; ++i) {
32         A[i].a = read(), A[i].b = read();
33         Num[++cnt] = A[i].a, Num[++cnt] = A[i].b;
34     }
35     sort(Num + 1, Num + cnt + 1);
36     int lim = cnt;cnt = 1;
37     for (int i=1; i<=lim; ++i) if (Num[i] != Num[cnt]) Num[++cnt] = Num[i];
38     for (int i=1; i<=n; ++i) {
39         A[i].a = lower_bound(Num + 1, Num + cnt + 1, A[i].a) - Num;
40         A[i].b = lower_bound(Num + 1, Num + cnt + 1, A[i].b) - Num;
41     }
42     for (int i=1; i<=cnt; ++i) fa[i] = i, fir[i] = Num[i];
43     for (int i=1; i<=n; ++i) {
44         int u = find(A[i].a), v = find(A[i].b);
45         if (u != v) {
46             fa[v] = u; tag[u] |= tag[v];
47             if (fir[v] > fir[u]) sec[u] = max(fir[u], sec[v]), fir[u] = fir[v];
48             else sec[u] = max(sec[u], fir[v]);
49         }
50         else if (tag[u]) {
51             puts("-1"); return 0;
52         }
53         else tag[u] = 1;
54     }
55     int Ans = 0;
56     for (int i=1; i<=cnt; ++i) {
57         if (i == find(i)) {
58             if (tag[i]) Ans = max(Ans, fir[i]);
59             else Ans = max(Ans, sec[i]);
60         }
61     }
62     cout << Ans;
63 
64     return 0;
65 }

 

posted @ 2018-09-14 15:24  MJT12044  阅读(175)  评论(0编辑  收藏  举报