题目传送门
题目大意
有$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 ", br[res]); 158 } 159 160 int main() { 161 init(); 162 descrete(); 163 solve(); 164 return 0; 165 }