[Codeforces] 1027F. Session in BSU

題目連結:https://codeforces.com/problemset/problem/1027/F
我好笨QAQ
本題關鍵大概是想到可以把每個考試當做邊來看吧OAO(看了解才知道
假設知道這件事後,那其實就很簡單,當然對於每個連通元件分開處理,明顯的如果邊數較點數多,那一定無法構造出一個合法的結果。
接著當邊數跟點數一樣多的時候,一定存在解,因為他必定可拆成幾個環跟一些連接的邊,那這時這裡的答案就是點的最大值。
還有邊數是點數減一的時候,不難發現他是顆樹,然後答案會是次大值。
邊數是點數減二的時候則不可能出現,所以討論這幾種狀況就可以得到答案了。
#include <bits/stdc++.h>
using namespace std;
using lld = int64_t;
using PII = pair<int,int>;
#define PB push_back
#define FF first
#define SS second
#define ALL(x) begin(x), end(x)
#define SZ(x) (static_cast<int>(std::size(x)))
const int N = 2000000 + 5;

class LiSan{
	private:
		vector<lld> vv;
	public:
		template<typename... Args>
		void insert(lld x, Args& ...oth){insert(x);insert(oth...);}
		void insert(lld x){vv.PB(x);}
		void done(){
			sort(ALL(vv));
			vv.resize(distance(vv.begin(), unique(ALL(vv))));
		}
		int size() const { return SZ(vv); }
		int get(lld x){
			return static_cast<int>(distance(vv.begin(), lower_bound(ALL(vv), x)));
		}
		lld inv_get(int x){return vv[x];}
		void clear(){vv.clear();}
} lisan;

class DJS{
	private:
		vector<int> arr;
	public:
		void init(int n){
			arr.resize(n);
			iota(ALL(arr), 0);
		}
		int query(int x){
			if(arr[x] != x) arr[x] = query(arr[x]);
			return arr[x];
		}
		void merge(int x, int y){arr[query(x)]=query(y);}
} djs;

PII arr[N], mx[N];
int egs[N], vtx[N];

int main() {
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n; cin >> n;
	for(int i=0;i<n;i++) cin >> arr[i].FF >> arr[i].SS;
	for(int i=0;i<n;i++) lisan.insert(arr[i].FF, arr[i].SS);
	lisan.done();
	for(int i=0;i<n;i++) arr[i].FF = lisan.get(arr[i].FF), arr[i].SS=lisan.get(arr[i].SS);
	djs.init(SZ(lisan));
	for(int i=0;i<n;i++) djs.merge(arr[i].FF, arr[i].SS);
	for(int i=0;i<n;i++) egs[djs.query(arr[i].FF)]++;
	for(int i=0;i<SZ(lisan);i++){
		int id = djs.query(i), val = lisan.inv_get(i);
		vtx[id]++;
		if(val >= mx[id].FF) mx[id].SS = mx[id].FF, mx[id].FF = val;
		else if(val > mx[id].SS) mx[id].SS = val;
	}
	int ans = -1;
	for(int i=0;i<SZ(lisan);i++){
		if(egs[i] > vtx[i]){
			ans = -1;
			break;
		}else if(egs[i] == vtx[i])
			ans = max(ans, mx[i].FF);
		else if(egs[i] == vtx[i]-1)
			ans = max(ans, mx[i].SS);
	}
	cout << ans << '\n';
	return 0;
}

留言

這個網誌中的熱門文章

[TIOJ] 1902. 「殿仁.王,不認識,誰啊?」,然後他就死了……

[NPSC] 2009初賽 E. 檸檬汽水傳說

[AtCoder] [經典競程 90 題] 024 - Select +/- One(★2)