Codeforces 1027F Session in BSU - 并查集

题目传送门

  传送门I

  传送门II

  传送门III

题目大意

  有$n​$门科目有考试,第$i​$门科目有两场考试,时间分别在$a_i, b_i\ \ (a_i < b_i)​$,要求每门科目至少参加一场考试,不能在同一个时间参加两场考试,问最后参加的考试最早的时间是什么。

  这几天,我怎么做的都是水题Emm....

  考虑先将$a_i, b_i$离散化。

  对于每一门考试,在$a_i, b_i$间连一条无向边。

  对于每个连通块,讨论:

  • 如果边数大于点数,显然无解
  • 如果边数等于点数,那么答案必须大于等于点权中的最大值。
  • 如果边数小于点数,那么最大不可用的时候会产生若干个基环树,所以答案必须大于等于点权中的次大值。

  并查集随便维护一下就行了。

Code

  1 /**
  2  * Codeforces
  3  * Problem#1027F
  4  * Accepted
  5  * Time: 873ms
  6  * Memory: 63000k
  7  */
  8 #include <algorithm>
  9 #include <iostream>
 10 #include <cstdlib>
 11 #include <cstdio>
 12 #include <vector>
 13 using namespace std;
 14 typedef bool boolean;
 15 
 16 template <typename T>
 17 void pfill(T* pst, const T* ped, T val) {
 18     for ( ; pst != ped; *(pst++) = val);
 19 }
 20 
 21 typedef class Input {
 22     protected:
 23         const static int limit = 65536;
 24         FILE* file; 
 25 
 26         int ss, st;
 27         char buf[limit];
 28     public:
 29         
 30         Input():file(NULL)    {    };
 31         Input(FILE* file):file(file) {    }
 32 
 33         void open(FILE *file) {
 34             this->file = file;
 35         }
 36 
 37         void open(const char* filename) {
 38             file = fopen(filename, "r");
 39         }
 40 
 41         char pick() {
 42             if (ss == st)
 43                 st = fread(buf, 1, limit, file), ss = 0;//, cerr << "str: " << buf << "ed " << st << endl;
 44             return buf[ss++];
 45         }
 46 }Input;
 47 
 48 #define digit(_x) ((_x) >= '0' && (_x) <= '9')
 49 
 50 Input& operator >> (Input& in, unsigned& u) {
 51     char x;
 52     while (~(x = in.pick()) && !digit(x));
 53     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 54     return in;
 55 }
 56 
 57 Input& operator >> (Input& in, unsigned long long& u) {
 58     char x;
 59     while (~(x = in.pick()) && !digit(x));
 60     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 61     return in;
 62 }
 63 
 64 Input& operator >> (Input& in, int& u) {
 65     char x;
 66     while (~(x = in.pick()) && !digit(x) && x != '-');
 67     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
 68     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 69     u *= aflag;
 70     return in;
 71 }
 72 
 73 Input& operator >> (Input& in, long long& u) {
 74     char x;
 75     while (~(x = in.pick()) && !digit(x) && x != '-');
 76     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
 77     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 78     u *= aflag;
 79     return in;
 80 }
 81 
 82 Input in (stdin);
 83 
 84 #define pii pair<int, int>
 85 
 86 int n, m;
 87 int *uf;
 88 int *es;
 89 int *mx, *smx;
 90 pii* ps;
 91 vector<int> br;
 92 
 93 int find(int x) {
 94     return (uf[x] == x) ? (x) : (uf[x] = find(uf[x]));
 95 }
 96 
 97 inline void init() {
 98     in >> n;
 99     ps = new pii[(n + 1)];
100     for (int i = 1; i <= n; i++)
101         in >> ps[i].first >> ps[i].second;
102 }
103 
104 inline void descrete() {
105     for (int i = 1; i <= n; i++) {
106         br.push_back(ps[i].first);
107         br.push_back(ps[i].second);
108     }
109     sort(br.begin(), br.end());
110     m = unique(br.begin(), br.end()) - br.begin();
111     for (int i = 1; i <= n; i++) {
112         ps[i].first = lower_bound(br.begin(), br.begin() + m, ps[i].first) - br.begin();
113         ps[i].second = lower_bound(br.begin(), br.begin() + m, ps[i].second) - br.begin();
114     }
115 }
116 
117 void addEdge(int u, int v) {
118     if (find(u) != find(v)) {
119         u = find(u), v = find(v);
120         es[u] += es[v];
121         if (mx[u] < mx[v])
122             smx[u] = mx[u], mx[u] = mx[v];
123         else if (smx[u] < mx[v])
124             smx[u] = mx[v];
125         smx[u] = ((smx[u] > smx[v]) ? (smx[u]) : (smx[v]));
126         uf[v] = u;
127     }
128     es[find(u)]++;
129 }
130 
131 int res = -1;
132 inline void solve() {
133     uf = new int[m];
134     es = new int[m];
135     mx = new int[m];
136     smx = new int[m];
137 
138     for (int i = 0; i < m; i++)
139         uf[i] = i, es[i] = -1, mx[i] = i, smx[i] = -1;
140     for (int i = 1; i <= n; i++)
141         addEdge(ps[i].first, ps[i].second);
142     for (int i = 0; i < m; i++)
143         if (find(i) == i) {
144             if (es[i] > 0) {
145                 res = -1;
146                 break;
147             }
148             if (!es[i])
149                 res = max(res, mx[i]);
150             else
151                 res = max(res, smx[i]);
152         }
153     
154     if (res == -1)
155         puts("-1");
156     else
157         printf("%d\n", br[res]);
158 }
159 
160 int main() {
161     init();
162     descrete();
163     solve();
164     return 0;
165 }
posted @ 2018-10-25 22:56 阿波罗2003 阅读(...) 评论(...) 编辑 收藏