TIOJ-1915

定義一張圖$G$的代價為:
$$\max_{u\in G} |{v|v>u\wedge (v, u)\text{ is adjancent}}|$$

現在給你一張圖,求原圖代價與重新分配點編號後的最小代價。

$N\le 5\times 10^5, E\le 8\times 10^5$,無重邊,無自環,不保證連通。


對於節點0來說,他所在的相鄰點數量就會是他自身的代價,而我們要讓他盡量小,且他相鄰的點都不會將他視為代價。
從0到$N-1$,不斷選擇當前度數最少的點,且將該點從圖上拔掉(相鄰點的度數都-1)。

可以用heap維護此操作,時間複雜度$O((N+E)log(N+E))$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
-------------- | /
| | /
| | /
| * |/ | | ------ *
| | | | / \
| | |\ | | | |\ |
\ | | | \ | | | | \ |
\ | | | \ | | \ / \ |
V | | \ \__/| ----- \ |
*/
#include <bits/stdc++.h>
using namespace std;

#define EmiliaMyWife ios::sync_with_stdio(0); cin.tie(NULL);
#define mem(i,j) memset(i,j,sizeof (i));
using ll = int64_t;
using ull = uint64_t;
using ld = long double;
using uint = uint32_t;
const double EPS = 1e-8;
const int INF = 0x3F3F3F3F;
const ll LINF = 4611686018427387903;
const int MOD = 1e9+7;
/*-----------------------------------------------------------------------------------------------------*/

signed main() {
EmiliaMyWife

int t;
cin >> t;
while(t--) {
int n, m;
cin >> n >> m;
vector<vector<int>> edge(n);
vector<int> cnt(n);
vector<bool> vis(n);
for(int i = 0, a, b; i < m; i++)
cin >> a >> b, edge[a].push_back(b), edge[b].push_back(a), cnt[a]++, cnt[b]++;
int ans = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for(int i = 0; i < n; i++) {
int res = 0;
for(int a : edge[i])
if(a > i)
res++;
ans = max(ans, res);
pq.push({cnt[i], i});
}
cout << ans << ' ';
ans = 0;
while(!pq.empty()) {
auto [a, b] = pq.top();
pq.pop();
if(vis[b])
continue;
vis[b] = 1;
ans = max(ans, a);
for(int x : edge[b]) {
if(!vis[x]) {
cnt[x]--;
pq.push({cnt[x], x});
}
}
}
cout << ans << '\n';
}

return 0;
}

這解跑得好慢orz,不知道有沒有常數小的寫法。