拓扑排序

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
// C++ Version
vector<int> G[MAXN]; // vector 实现的邻接表
int c[MAXN]; // 标志数组
vector<int> topo; // 拓扑排序后的节点

bool dfs(int u) {
c[u] = -1;
for (int v : G[u]) {
if (c[v] < 0)
return false;
else if (!c[v])
if (!dfs(v)) return false;
}
c[u] = 1;
topo.push_back(u);
return true;
}

bool toposort() {
topo.clear();
memset(c, 0, sizeof(c));
for (int u = 0; u < n; u++)
if (!c[u])
if (!dfs(u)) return false;
reverse(topo.begin(), topo.end());
return true;
}

欧拉回路

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
struct node{
int to, next;
int flag;
}edge[maxn];
int head[maxn], cnt = -1;
inline void add(int u, int v){
edge[++cnt].to = v;
edge[cnt].flag = 1;
edge[cnt].next = head[u];
head[u] = cnt;
}
stack<int> s;
inline void dfs(int now){
s.push(now);
for(int i = head[now];~i;i = edge[i].next){
if(edge[i].flag){
edge[i].flag = 0;
edge[i^1].flag = 0;
dfs(edge[i].to);
break;
}
}
}

inline void fleury(int st){
s.push(st);
while(!s.empty()){
int now = s.top();
s.pop();
int f = 0;
for(int i = head[now];~i;i = edge[i].next){
if(edge[i].flag){
f = 1;
break;
}
}
if(f){
dfs(now);
}else{
write(' ', now);
}
}
puts("");
}

int d[maxn];
inline void solve(void){
memset(head, -1, sizeof(head));
int n, m;
read(n, m);
int u, v;
for(int i = 0;i < m;i++){
read(u, v);
d[u]++;
d[v]++;
add(u, v);
add(v, u);
}
int st = 1;
int num = 0;
for(int i = 1;i <= n;i++){
if(d[i] % 2 == 1){
num++;
st = i;
}
}
if(num == 0 || num == 2) fleury(st);
else puts("No solution");
}
signed main(void){

#ifdef _DEBUG
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif

int t = 1;
// read(t);
while(t--){
solve();
}

return 0;
}

最短路

dijstra

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define int ll
#define INF 0x3f
typedef pair<int, int> PII;
const int maxn = 1e5 + 5;
const int maxm = 5e5 + 5;
struct node{
int to;
int w;
int next;
}edge[maxm];
int head[maxn], cnt;
inline void add(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
int dis[maxn];
bool vis[maxn];
//普通dijstra
inline void dijstra1(int st, int n){
memset(dis, INF, sizeof(dis));
dis[st] = 0;
for(int i = 0;i < n;i++){
int u = -1, min = dis[0];
for(int j = 1;j <= n;j++){
if(vis[j] == false && dis[j] < min){
u = j;
min = dis[j];
}
}
if(u == -1) break;
vis[u] = true;
for(int i = head[u];i;i = edge[i].next){
if(vis[edge[i].to] == false && dis[edge[i].to] > dis[u] + edge[i].w){
dis[edge[i].to] = dis[u] + edge[i].w;
}
}
}

}
//堆优化之后的dijstra
inline void dijstra(int st, int n){
memset(dis, INF, sizeof(dis));
dis[st] = 0;
priority_queue<PII, vector<PII>, greater<PII> > heap;
heap.push({0, st});
PII t;
while(!heap.empty()){
t = heap.top();
heap.pop();
int now = t.second, distance = t.first;
if(vis[now]) continue;
vis[now] = true;
for(int i = head[now];i;i = edge[i].next){
if(dis[edge[i].to] > dis[now] + edge[i].w){
dis[edge[i].to] = dis[now] + edge[i].w;
heap.push({dis[edge[i].to], edge[i].to});
}
}
}
}
signed main(void){
int n, m, st;
cin>>n>>m>>st;
for(int i = 0;i < m;i++){
int u, v, w;
cin>>u>>v>>w;
add(u, v, w);
if(u == st) dis[v] = w;
}
dijstra(st, n);
for(int i = 1;i <= n;i++){
if(dis[i] == dis[0]) cout<<(2147483647);
else cout<<(dis[i]);
putchar(' ');
}
return 0;
}

spfa

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
#define ll long long
#define int ll
#define INF 0x3f
const int maxn = 1e5+5;
const int maxm = 5e5+5;
const int inf = 2147483647;
struct node{
int to;
int next;
ll w;
}edge[maxm];
int head[maxn], cnt;
inline void add(int u, int v, ll w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
bool vis[maxn];
ll dis[maxn];
int num_cnt[maxn];
// SLF优化后的spfa
inline int spfa1(int st, int aim, int n){
memset(dis, INF, sizeof(dis));
dis[st] = 0;
deque<int> que;
que.push_back(st);
vis[st] = 1;
int now;
num_cnt[st] = 1;
int flag = 1;
while(!que.empty()){
now = que.front();
que.pop_front();
vis[now] = 0;
for(int i = head[now];i;i = edge[i].next){
if(dis[now] + edge[i].w < dis[edge[i].to]){
dis[edge[i].to] = dis[now] + edge[i].w;
num_cnt[edge[i].to] = num_cnt[now] + 1;
if(num_cnt[edge[i].to] > n) flag = 0;
if(!vis[edge[i].to]){
if(!que.empty() && dis[edge[i].to] >= dis[que.front()]) que.push_back(edge[i].to);
else que.push_front(edge[i].to);
vis[edge[i].to] = 1;
}
}
}
}
return flag;
}
// LLL优化后spfa
inline int spfa2(int st, int aim, int n){
queue<int> que;
memset(dis, INF, sizeof(dis));
que.push(st);
vis[st] = true;
dis[st] = 0;
int num = 1;
int sum = 0;
num_cnt[st] = 1;
int flag = 1;
while(!que.empty()){
int now = que.front();
while(dis[now] * num > sum){
que.pop();
que.push(now);
now = que.front();
}
que.pop();
num--;
sum -= dis[now];
vis[now] = false;
for(int i = head[now];i;i = edge[i].next){
if(dis[edge[i].to] > dis[now] + edge[i].w){
dis[edge[i].to] = dis[now] + edge[i].w;
num_cnt[edge[i].to] = num_cnt[now] + 1;
if(num_cnt[edge[i].to] > n) flag = 0;
if(!vis[edge[i].to]){
que.push(edge[i].to);
sum += dis[edge[i].to];
num++;
vis[edge[i].to] = 1;
}
}
}
}
return flag;
}
// LLL+SLF优化
inline int spfa(int st, int aim, int n){
memset(dis, INF, sizeof(dis));
deque<int> que;
que.push_back(st);
vis[st] = true;
dis[st] = 0;
int num = 1;
int sum = 0;
num_cnt[st] = 1;
int flag = 1;
while(!que.empty()){
int now = que.front();
while(num * dis[now] > sum){
que.pop_front();
que.push_back(now);
now = que.front();
}
que.pop_front();
num--;
sum -= dis[now];
vis[now] = false;
for(int i = head[now];i;i = edge[i].next){
if(dis[edge[i].to] > dis[now] + edge[i].w){
dis[edge[i].to] = dis[now] + edge[i].w;
num_cnt[edge[i].to] = num_cnt[now] + 1;
if(num_cnt[edge[i].to] > n) flag = 0;
if(!vis[edge[i].to]){
if(!que.empty() &&(dis[edge[i].to] <= dis[que.front()])) que.push_front(edge[i].to);
else que.push_back(edge[i].to);
vis[edge[i].to] = true;
sum += dis[edge[i].to];
num++;
}
}
}
}
return flag;
}
signed main(void){
int n, m, s;
cin>>n>>m>>s;
for(int i = 0;i < m;i++){
int u, v;
ll w;
cin>>u>>v>>w;
add(u, v, w);
}
spfa(s, 0, n);
for(int i = 1;i <= n;i++){
if(dis[i] == dis[0]) cout<<(inf);
else cout<<(dis[i]);
putchar(' ');
}
return 0;
}

floyd

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
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define INF 0x3f
const int maxn = 505;
ll dis[maxn][maxn];
inline void floyd(int n){
for(int k = 1;k <= n;k++){
for(int i = 1;i <= n;i++){
if(dis[i][k] == dis[0][0]) continue;
for(int j = 1;j <= i;j++){
dis[i][j] = min(dis[i][j], (dis[i][k] + dis[k][j]));
dis[j][i] = dis[i][j];
}
}
}
}
signed main(void){
int n, m;
while(1){
cin>>n>>m;
if(n == 0 && m == 0) break;
memset(dis, INF, sizeof(dis));
for(int i = 0;i < m;i++){
int u, v, w;
cin>>u>>v>>w;
dis[u][v] = dis[v][u] = w;
}
floyd(n);
cout<<dis[1][n]<<endl;
}
return 0;
}

johnson

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<deque>
using namespace std;
#define ll long long
#define int ll
#define INF 0x3f
typedef pair<int, int> PII;
const int maxn = 1e3 + 5;
const int maxm = 1e5 + 5;
const int maxl = 1e9;
struct node{
int to;
int w;
int next;
}edge[maxm<<1];
int head[maxn], cnt;
inline void add(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
int dis[maxn];
int vis[maxn];
inline void dijstra(int st, int aim, int n){
priority_queue<PII, vector<PII>, greater<PII> > heap;
for(int i = 1;i <= n;i++) dis[i] = maxl;
memset(vis, 0, sizeof(vis));
dis[st] = 0;
heap.push(PII(0, st));
PII t;
while(!heap.empty()){
t = heap.top();
heap.pop();
int now = t.second;
if(vis[now]) continue;
vis[now] = 1;
for(int i = head[now];i;i = edge[i].next){
if(dis[edge[i].to] > dis[now] + edge[i].w){
dis[edge[i].to] = dis[now] + edge[i].w;
heap.push(PII(dis[edge[i].to], edge[i].to));
}
}
}
}
int h[maxn];
int num_cnt[maxn];
inline int spfa(int st, int aim, int n){
memset(vis, 0, sizeof(vis));
memset(h, INF, sizeof(h));
deque<int> que;
que.push_back(st);
vis[st] = 1;
h[st] = 0;
num_cnt[st] = 1;
int num = 1;
int sum = 0;
while(!que.empty()){
int now = que.front();
while(num * h[now] > sum){
que.pop_front();
que.push_back(now);
now = que.front();
}
que.pop_front();
num--;
sum -= h[now];
vis[now] = 0;
for(int i = head[now];i;i = edge[i].next){
if(h[edge[i].to] > h[now] + edge[i].w){
h[edge[i].to] = h[now] + edge[i].w;
num_cnt[edge[i].to] = num_cnt[now] + 1;
if(num_cnt[edge[i].to] > n) return 0;;
if(!vis[edge[i].to]){
if(!que.empty() && (h[edge[i].to] <= h[que.front()])) que.push_front(edge[i].to);
else que.push_back(edge[i].to);
vis[edge[i].to] = 1;
sum += h[edge[i].to];
num++;
}
}
}
}
return 1;
}
signed main(void){
int n, m;
while(1){
cnt = 0;
memset(head, 0, sizeof(head));
cin>>n>>m;
if(!n && !m) break;
for(int i = 1;i <= m;i++){
int u, v, w;
cin>>u>>v>>w;
add(u, v, w);
add(v, u, w);
}
for(int i = 1;i <= n;i++){
add(0, i, 0);
}
spfa(0, 1, n);
for(int now = 1;now <= n;now++){
for(int i = head[now];i;i = edge[i].next){
edge[i].w += h[now] - h[edge[i].to];
}
}
dijstra(1, n, n);
cout<<dis[n]<<endl;
}
return 0;
}

第K短路

AStar

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define INF 0x3f
typedef pair<int, int> PII;
const int maxn = 1000+50;
const int maxm = 100000 + 50;
struct Edge{
int to, w, next;
}edge[maxm<<1];
int headz[maxn], cnt;
int headf[maxn];
struct node{
int f, g, from;
bool operator < (node a) const{
if(a.f == f) return g>a.g;
return f>a.f;
}
};
inline void add1(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = headz[u];
headz[u] = cnt;
}
inline void add2(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = headf[u];
headf[u] = cnt;
}
int h[maxn];
bool vis[maxn];
inline int dijstra(int st, int ed, int n){
priority_queue<PII, vector<PII>, greater<PII> > q;
memset(h, INF, sizeof(h));
memset(vis, 0, sizeof(vis));
PII t;
int now;
h[st] = 0;
q.push(PII(h[st], st));
while(!q.empty()){
t = q.top();
q.pop();
now = t.second;
if(vis[now]) continue;
vis[now] = 1;
for(int i = headf[now];i;i = edge[i].next){
if(h[edge[i].to] > h[now] + edge[i].w){
h[edge[i].to] = h[now] + edge[i].w;
q.push(PII(h[edge[i].to], edge[i].to));
}
}
}
}
inline int AStar(int st, int ed, int k){
if(st == ed) k++;
if(h[st] == h[0]) return -1;
priority_queue<node> q;
int cnt = 0;
node tmp, to;
tmp.from = st;
tmp.g = 0;
tmp.f = tmp.g + h[tmp.from];
q.push(tmp);
while(!q.empty()){
tmp = q.top();
q.pop();
if(tmp.from == ed) cnt++;
if(cnt == k) return tmp.g;
for(int i = headz[tmp.from];i;i = edge[i].next){
to.from = edge[i].to;
to.g = tmp.g + edge[i].w;
to.f = to.g + h[to.from];
q.push(to);
}
}
return -1;
}
inline void init(void){
memset(headf, 0, sizeof(headf));
memset(headz, 0, sizeof(headz));
cnt = 0;
}
int main(void){
int n, m;
int u, v, w;
while(cin>>n>>m){
init();
for(int i = 0;i < m;i++){
cin>>u>>v>>w;
add1(u, v, w);
add2(v, u, w);
}
int s, t, k;
cin>>s>>t>>k;
dijstra(t, s, n);
cout<<AStar(s, t, k)<<endl;
}
return 0;
}

树的直径

无负边

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
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
#define ll long long
#define PII pair<ll, ll>
const int maxn = 1e4+5, maxm = 2e4+5;
struct node{
int to, next;
ll w;
}edge[maxm];
int head[maxn], cnt;
void add(int u, int v, ll w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
ll dis[maxn];
int vis[maxn];
void bfs(int st){
queue<int> q;
memset(vis, 0, sizeof(vis));
q.push(st);
dis[st] = 0;
int now;
while(!q.empty()){
now = q.front();
q.pop();
vis[now] = 1;
for(int i = head[now];i;i = edge[i].next){
int to = edge[i].to;
if(vis[to]) continue;
dis[to] = dis[now] + edge[i].w;
q.push(to);
}
}
}
int main(void){
int u, v;
ll w;
int n = 0;
while(scanf("%d %d %lld", &u, &v, &w) != EOF){
add(u, v, w);
add(v, u, w);
// cout<<u<<v<<w<<endl;
n = max(u, v);
}
int st = 1;
bfs(st);
ll maxx = 0;
for(int i = 1; i <= n;i++){
if(dis[i] > maxx){
st = i;
maxx = dis[i];
}
}
bfs(st);
maxx = 0;
for(int i = 1; i <= n;i++){
if(dis[i] > maxx){
st = i;
maxx = dis[i];
}
}
printf("%lld\n", maxx);
}

有负边

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
const int N = 10000 + 10;

int n, d = 0;
int d1[N], d2[N];
vector<int> E[N];

void dfs(int u, int fa) {
d1[u] = d2[u] = 0;
for (int v : E[u]) {
if (v == fa) continue;
dfs(v, u);
int t = d1[v] + 1;
if (t > d1[u])
d2[u] = d1[u], d1[u] = t;
else if (t > d2[u])
d2[u] = t;
}
d = max(d, d1[u] + d2[u]);
}

int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d %d", &u, &v);
E[u].push_back(v), E[v].push_back(u);
}
dfs(1, 0);
printf("%d\n", d);
return 0;
}

最小生成树

prim

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
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 5e3 + 4;
const int maxm = 2e5 + 5;
const int inf = 0x7ffffff;
struct node{
int to, w, next;
}edge[maxm<<1];
int head[maxn], cnt;
inline void add(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
int tot, now, ans, dis[maxn],vis[maxn];
int n, m;
int jd;
inline int prim(void){
now = 1;
for(int i = 2;i <= n;i++){
dis[i] = inf;
}
for(int i = head[now];i;i = edge[i].next){
dis[edge[i].to] = min(dis[edge[i].to], edge[i].w);
}
while(++tot < n){
jd = 0;
int minn = inf;
vis[now] = 1;
for(int i = 1;i <= n;i++){
if(!vis[i] && minn > dis[i]){
minn = dis[i];
now = i;
jd = 1;
}
}
if(!jd) return 0;
ans += minn;
for(int i = head[now];i;i = edge[i].next){
if(!vis[edge[i].to])
dis[edge[i].to] = min(dis[edge[i].to], edge[i].w);
}
}
return ans;
}
signed main(void){
cin>>n>>m;
for(int i = 0;i < m;i++){
int u, v, w;
cin>>u>>v>>w;
add(u, v, w);
add(v, u, w);
}
prim();
if(jd) cout<<ans;
else cout<<"orz";
return 0;
}

KrusKal

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
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 5e3 + 5;
const int maxm = 4e5 + 5;
int id[maxn];
inline void init(int n){
for(int i = 1;i <= n;i++) id[i] = i;
}
inline int find(int p){
if(p == id[p]) return p;
return id[p] = find(id[p]);
}
struct edge{
int from, to, w;
}edge[maxm];
inline int cmp(struct edge p, struct edge q){
return p.w < q.w;
}
int n, m;
int ans, tot;
inline void kruskal(void){
sort(edge, edge + m, cmp);
for(int i = 0;i < m;i++){
int rootp = find(edge[i].from);
int rootq = find(edge[i].to);
if(rootq == rootp) continue;
ans += edge[i].w;
id[rootq] = rootp;
if(++tot == n-1) break;
}
}
signed main(void){
cin>>n>>m;
init(n);
for(int i = 0;i < m;i++){
cin>>edge[i].from>>edge[i].to>>edge[i].w;
}
kruskal();
if(tot == n-1) cout<<ans;
else cout<<"orz";
return 0;
}

次小生成树

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
struct node{
int from, to, next;
ll w;
}edge[maxn<<1], e[N];

int head[maxn], cnt;
inline void add(int u,int v, ll w){
edge[++cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int cmp(node a, node b){
return a.w < b.w;
}

// 并查集
int id[maxn];
inline void init(void){
for(int i = 0; i < maxn;i++) id[i] = i;
cnt = 0;
}
inline int find(int p){
if(p == id[p]) return p;
return id[p] = find(id[p]);
}
inline int funion(int p, int q){
int fp = find(p);
int fq = find(q);
if(fp == fq) return 0;
id[fp] = fq;
return 1;
}

// 最小生成树
int n, m;
int flag[N];
inline ll krusral(void){
init();
sort(e, e+m, cmp);
ll ans = 0;
for(int i = 0;i < m;i++){
if(funion(e[i].from, e[i].to)){
flag[i] = 1;
add(e[i].from, e[i].to, e[i].w);
add(e[i].to, e[i].from, e[i].w);
ans += e[i].w;
}
}
return ans;
}

// 树上倍增
ll mx[maxn][20];
ll smx[maxn][20];
int fa[maxn][20];
int deep[maxn];
inline void dfs(int now, int f){
deep[now] = deep[f]+1;
fa[now][0] = f;
for(int i = 1;i <= (int)log2(deep[now]);i++){
fa[now][i] = fa[fa[now][i-1]][i-1];
mx[now][i] = max(mx[now][i-1], mx[fa[now][i-1]][i-1]);
if(mx[now][i-1] == mx[fa[now][i-1]][i-1])
smx[now][i] = max(smx[now][i-1], smx[fa[now][i-1]][i-1]);
else
smx[now][i] = max(min(mx[now][i-1], mx[fa[now][i-1]][i-1]),
max(smx[now][i-1], smx[fa[now][i-1]][i-1]));
}
for(int i = head[now];i;i = edge[i].next){
if(edge[i].to == f) continue;
mx[edge[i].to][0] = edge[i].w;
smx[edge[i].to][0] = -1;
dfs(edge[i].to, now);
}
}

inline ll lca(int u, int v, ll w){
if(u == v) return (ll)1e9;
ll ans1 = 0, ans2 = 0;
if(deep[u] < deep[v]) swap(u, v);
while(deep[u] > deep[v]){
int mid = (int)log2(deep[u] - deep[v]);
if(mx[u][mid] == ans1){
ans2 = max(ans2, smx[u][mid]);
}else{
ans2 = max(min(ans1, mx[u][mid]),
max(ans2, smx[u][mid]));
}
ans1 = max(ans1, mx[u][mid]);
u = fa[u][mid];
}
if(u == v) return ((w - ans1) == 0) ? (w - ans2) : (w-ans1);
for(int i = (int)log2(deep[u]);i >= 0;i--){
if(fa[u][i] != fa[v][i]){
if(mx[u][i] == ans1)
ans2 = max(ans2, smx[u][i]);
else{
ans2 = max(min(ans1, mx[u][i]),
max(ans2, smx[u][i]));
}
ans1 = max(ans1, mx[u][i]);

if(mx[v][i] == ans1)
ans2 = max(ans2, smx[v][i]);
else{
ans2 = max(min(ans1, mx[v][i]),
max(ans2, smx[v][i]));
}
ans1 = max(ans1, mx[v][i]);
u = fa[u][i];
v = fa[v][i];
}
}
int i = 0;
if(mx[u][i] == ans1)
ans2 = max(ans2, smx[u][i]);
else{
ans2 = max(min(ans1, mx[u][i]),
max(ans2, smx[u][i]));
}
ans1 = max(ans1, mx[u][i]);

if(mx[v][i] == ans1)
ans2 = max(ans2, smx[v][i]);
else{
ans2 = max(min(ans1, mx[v][i]),
max(ans2, smx[v][i]));
}
ans1 = max(ans1, mx[v][i]);
return ((w - ans1) == 0) ? (w - ans2) : (w-ans1);
}

inline void solve(void){
read(n, m);
for(int i = 0;i < m;i++){
read(e[i].from, e[i].to, e[i].w);
}
ll temp = krusral();
dfs(1, 0);
ll ans = 1e9;
for(int i = 0;i < m;i++){
if(!flag[i]){
ll mid = lca(e[i].from, e[i].to, e[i].w);
ans = min(ans, mid);
}
}
write('\n', temp + ans);
}

signed main(void){

#ifdef _DEBUG
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif

int t = 1;
// read(t);
while(t--){
solve();
}

return 0;
}

最小树形图

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
struct DMST{
private:
#define maxn 1010
#define maxm 400010
struct node{
int u, v, w;
}edge[maxm];
int pre[maxn], id[maxn], vis[maxn], in[maxn];
int cnt;
public:
void init(void){
cnt = 0;
}
void add(int u, int v, int w){
edge[cnt] = {u, v, w};
cnt++;
}
int zhuliu(int root, int n) {
int res = 0, u, v;
while(1){
// cout<<"now"<<endl;
memset(in, 0x3f, sizeof(in));
for(int i = 0;i < cnt;i++){
if(edge[i].u != edge[i].v && edge[i].w < in[edge[i].v]){
in[edge[i].v] = edge[i].w;
pre[edge[i].v] = edge[i].u;
}
}
for(int i = 1;i <= n;i++){
if(i != root && in[i] == in[0]) return -1;
}
int tn = 1;
memset(id, 0, sizeof(id));
memset(vis, 0, sizeof(vis));
in[root] = 0;
for(int i = 1;i <= n;i++){
res += in[i];
v = i;
while(vis[v] != i && id[v] == 0 && v != root){ // 找环
vis[v] = i;
v = pre[v];
}
if(v != root && id[v] == 0){
for(int u = pre[v];u != v;u = pre[u]){ // 缩点
id[u] = tn;
}
id[v] = tn++;
}
}
if(tn == 1) break;
for(int i = 1;i <= n;i++){
if(id[i] == 0) id[i] = tn++;
}
for(int i = 0;i < cnt;){
v = edge[i].v;
edge[i].u = id[edge[i].u];
edge[i].v = id[edge[i].v];
if(edge[i].u != edge[i].v) edge[i++].w -= in[v];
else swap(edge[i], edge[--cnt]);
}
n = tn-1;
root = id[root];
}
return res;
}
}dmst;

lca

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
const int maxn = 5e5 + 5;
struct LCA{
private:
struct node{
int to, next;
ll w;
}edge[maxn << 1];
int head[maxn], cnt;
int fa[maxn][20];
public:
int depth[maxn];
void init(void){
memset(head,0, sizeof(head));
cnt = 0;
}
void add(int u, int v, ll w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int now, int fath){
depth[now] = depth[fath] + 1;
fa[now][0] = fath;
for(int i = 1;i < 20;i++){
fa[now][i] = fa[fa[now][i-1]][i-1];
}
for(int i = head[now];i;i = edge[i].next){
int to = edge[i].to;
if(to == fath) continue;
dfs(to, now);
}
}
int query(int u, int v){
if(depth[u] < depth[v]) swap(u, v);
for(int i = 19;i >= 0;i--){
if(depth[u] - (1 << i) >= depth[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = 19;i >= 0;i--){
if(fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
}lca;

二分图

匈牙利算法

$O(nm)$

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
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxm = 1000050;
const int maxn = 1050;
struct node{
int to, next;
}edge[maxm];
int flag[maxn][maxn];
int head[maxn], cnt;
inline void add(int u, int v){
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int id[maxn];//原配
int vis[maxn];
inline int dfs(int now){
for(int i = head[now];i;i = edge[i].next){
if(!vis[edge[i].to]){
vis[edge[i].to] = 1;
if(!id[edge[i].to] || dfs(id[edge[i].to])){
id[edge[i].to] = now;
return 1;
}
}
}
return 0;
}
inline int hungarian(int n){
int ans;
for(int i = 1;i <= n;i++){
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
return ans;
}
signed main(void){
int n, m, e;
scanf("%d %d %d", &n, &m, &e);
int u, v;
for(int i = 0;i < e;i++){
scanf("%d %d",&u, &v);
if(!flag[u][v])
add(u, v),flag[u][v] = 1;
}
printf("%d", hungarian(n));
return 0;
}

Hopcroft-Carp (HK)

$O(\sqrt{n} m)$

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
#define ll long long
const int maxn = 3005;
const int maxm = maxn * maxn;
const int INF = 0x3f3f3f3f;
struct peop{
int x, y, v;
}p[maxn];
struct unbr{
int x, y;
}u[maxn];
struct node{
int to, next;
}edge[maxm];
int head[maxn], cnt;
inline void add(int u, int v){
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int m, n;
int id[maxn << 1], dis[maxn << 1];
inline int bfs(void){
memset(dis, 0, sizeof(dis));
queue<int> q;
for(int i = 1;i <= m;i++){
if(!id[i]) q.push(i);
}
int flag = 0;
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = head[now];i;i = edge[i].next){
if(!dis[edge[i].to]){
dis[edge[i].to] = dis[now] + 1;
if(!id[edge[i].to]) flag = 1;
else dis[id[edge[i].to]] = dis[edge[i].to] + 1, q.push(id[edge[i].to]);
}
}
}
return flag;
}
inline int dfs(int now){
for(int i = head[now];i;i = edge[i].next){
if(dis[edge[i].to] == dis[now] + 1){
dis[edge[i].to] = 0;
if(!id[edge[i].to] || dfs(id[edge[i].to])){
id[edge[i].to] = now;
id[now] = edge[i].to;
return 1;
}
}
}
return 0;
}

inline int solve(void){
int ans = 0;
while(bfs()){
for(int i = 1;i <= m;i++){
if(!id[i] && dfs(i)) ans++;
}
}
return ans;
}

inline void init(void){
memset(head, 0, sizeof(head));
cnt = 0;
memset(id, 0, sizeof(id));
}
int t;
inline int check(int a, int b){
int x = p[a].x - u[b].x;
int y = p[a].y - u[b].y;
if((ll)p[a].v * t * p[a].v * t >= (ll)x * x + (ll)y * y) return 1;
return 0;
}
int main(void){
int T;
scanf("%d",&T);
int c = 0;
while(T--){
c++;
init();
scanf("%d",&t);
scanf("%d", &m);
for(int i = 1;i <= m;i++){
scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].v);
}
scanf("%d", &n);
for(int i = 1;i <= n;i++){
scanf("%d %d", &u[i].x, &u[i].y);
for(int j = 1;j <= m;j++){
if(check(j, i)){
add(j, i + m);
}
}
}
printf("Scenario #%d:\n%d\n\n", c, solve());
}
return 0;
}

最优匹配

dfs

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
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int MAXN = 305;
const int INF = 0x3f3f3f3f;

int love[MAXN][MAXN]; // 记录每个妹子和每个男生的好感度
int ex_girl[MAXN]; // 每个妹子的期望值
int ex_boy[MAXN]; // 每个男生的期望值
bool vis_girl[MAXN]; // 记录每一轮匹配匹配过的女生
bool vis_boy[MAXN]; // 记录每一轮匹配匹配过的男生
int match[MAXN]; // 记录每个男生匹配到的妹子 如果没有则为-1
int slack[MAXN]; // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
int N;
bool dfs(int girl)
{
vis_girl[girl] = true;
for (int boy = 0; boy < N; ++boy) {
if (vis_boy[boy]) continue;
int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
if (gap == 0) {
vis_boy[boy] = true;
if (match[boy] == -1 || dfs( match[boy] )) {
match[boy] = girl;
return true;
}
} else {
slack[boy] = min(slack[boy], gap);
}
}
return false;
}

int KM()
{
memset(match, -1, sizeof match);
memset(ex_boy, 0, sizeof ex_boy);

for (int i = 0; i < N; ++i) {
ex_girl[i] = love[i][0];
for (int j = 1; j < N; ++j) {
ex_girl[i] = max(ex_girl[i], love[i][j]);
}
}
for (int i = 0; i < N; ++i) {
fill(slack, slack + N, INF);
while (1) {
memset(vis_girl, false, sizeof vis_girl);
memset(vis_boy, false, sizeof vis_boy);

if (dfs(i)) break;
int d = INF;
for (int j = 0; j < N; ++j)
if (!vis_boy[j]) d = min(d, slack[j]);
for (int j = 0; j < N; ++j) {
if (vis_girl[j]) ex_girl[j] -= d;
if (vis_boy[j]) ex_boy[j] += d;
else slack[j] -= d;
}
}
}
int res = 0;
for (int i = 0; i < N; ++i)
res += love[ match[i] ][i];

return res;
}

int main()
{
while (~scanf("%d", &N)) {

for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
scanf("%d", &love[i][j]);
printf("%d\n", KM());
}
return 0;
}

bfs

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 505;
const int maxm = 250005;
struct node{
int to, next;
ll w;
}edge[maxm];
int head[maxn], cnt;
void add(int u, int v, ll w){
edge[++cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
ll numl[maxn], numr[maxn], slack[maxn];
int idl[maxn], idr[maxn], pre[maxn];
int visl[maxn], visr[maxn];
int n;

queue<int> q;
void aug(int now){
int t;
while(now){
t = idl[pre[now]];
idl[pre[now]] = now;
idr[now] = pre[now];
now = t;
}
}
void bfs(int now){
memset(visl, 0, sizeof(visl));
memset(visr, 0, sizeof(visr));
memset(slack, 0x3f, sizeof(slack));

while(!q.empty()) q.pop();
q.push(now);

while(1){
while(!q.empty()){
int u = q.front();q.pop();
visl[u] = 1;
for(int i = head[u];i;i = edge[i].next){
int to = edge[i].to;
if(!visr[to]){
int temp = numl[u] + numr[to] - edge[i].w;
if(temp < slack[to]){
slack[to] = temp;
pre[to] = u;
if(slack[to] == 0){
visr[to] = 1;
if(!idr[to]){
aug(to);
return;
}else q.push(idr[to]);
}
}
}
}
}
ll d = 0x3f3f3f3f3f3f3f;
for(int i = 1;i <= n;i++) if(!visr[i]) d = min(d, slack[i]);
for(int i = 1;i <= n;i++){
if(visl[i]) numl[i] -= d;
if(visr[i]) numr[i] += d;
else slack[i] -= d;
}
for(int i = 1;i <= n;i++){
if(!visr[i]){
if(slack[i] == 0){
visr[i] = 1;
if(!idr[i]){
aug(i);
return;
}else q.push(idr[i]);
}
}
}
}
}
ll km(void){
ll ans = 0;
for(int i = 1;i <= n;i++){
bfs(i);
}
for(int i = 1;i <= n;i++){
if(idr[i]) ans += numr[i] + numl[idr[i]];
}
return ans;
}
int main(void){
int m;
cin>>n>>m;
int u, v;
ll w;
for(int i = 0;i < m;i++){
cin>>u>>v>>w;
add(u, v, w);
numl[u] = max(numl[u], w);
}
// cout<<"debug"<<endl;
cout<<km()<<endl;
for(int i = 1;i <= n;i++) cout<<idr[i]<<" ";
return 0;
}

tarjan

缩点

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
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
const int maxn = 2e4 + 5, maxm = 5e4 + 5;
struct node {
int to, next;
} edge[maxm];
int head[maxn], cnt;
void add(int u, int v) {
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int dfn[maxn], low[maxn];
int vis[maxn];
int id[maxn];
int dfntmp;
int num;
stack<int> s;
void tarjan(int now) {
dfn[now] = low[now] = ++dfntmp;
s.push(now);
vis[now] = 1;
for (int i = head[now]; i; i = edge[i].next) {
int to = edge[i].to;
if (!dfn[to]) {
tarjan(to);
low[now] = min(low[now], low[to]);
} else if (vis[to]) low[now] = min(low[now], dfn[to]);
}
if (dfn[now] == low[now]) {
num++;
int tmp;
do {
tmp = s.top();
s.pop();
id[tmp] = num;
vis[tmp] = 0;
} while (tmp != now);
}
}
std::vector<pair<int, int> > que;
int in[maxn];
int main(void) {
int n, m;
cin >> n >> m;
num = n;
int u, v;
for (int i = 0; i < m; i++) {
cin >> u >> v;
add(u, v);
que.push_back({v, u});
}
for (int i = 1; i <= n ; i++) {
if (!dfn[i]) tarjan(i);
}
for (int i = 0; i < m; i++) {
u = que[i].first;
v = que[i].second;
if(id[u] != id[v]){
in[id[v]]++;
}
}
int aim = 0;
for(int i = n+1;i <= num;i++){
if(in[i] == 0) {
if(aim != 0) {
cout<<0<<endl;
return 0;
}
aim = i;
}
}
int ans = 0;
for(int i = 1;i <= n;i++){
if(id[i] == aim) ans++;
}
cout<<ans<<endl;
return 0;
}

割点

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
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1005, maxm = 2000005;
struct node{
int to, next;
}edge[maxm];
int head[maxn], cnt;
void add(int u, int v){
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int dfn[maxn], low[maxn], dfntmp;
int flag[maxn];
int tot;
int root;
void tarjan(int now){
dfn[now] = low[now] = ++dfntmp;
int num = 0;
for(int i = head[now];i;i = edge[i].next){
int to = edge[i].to;
if(!dfn[to]){
tarjan(to);
low[now] = min(low[now], low[to]);
if(low[to] >= dfn[now]){
num++;
if(now != root || num > 1) flag[now] = 1;
}
}else low[now] = min(low[now], dfn[to]);
}
}
void init(void){
memset(head, 0, sizeof(head));
cnt = 0;
dfntmp = 0;
memset(dfn, 0, sizeof(dfn));
memset(flag, 0, sizeof(flag));
memset(low, 0, sizeof(low));;
}
int main(void){
int n;
char ch;
while(scanf("%d", &n) && n){
init();
int u, v;
while(scanf("%d", &u) && u){
ch = getchar();
while(ch != '\n'){
scanf("%d", &v);
add(u, v);
add(v, u);
// printf("%d %d\n", u, v);
ch = getchar();
}
}
for(int i = 1;i <= n;i++){
if(!dfn[i]) root = i, tarjan(i);
}
int ans = 0;
for(int i = 1;i <= n;i++){
if(flag[i]) ans++;
}
printf("%d\n", ans);
}
return 0;
}

割点后强连通块数量

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
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <map>
using namespace std;
const int maxn = 1e3+5, maxm = 2e6+5;;
struct node {
int to, next;
} edge[maxm];
int head[maxn], cnt = -1;
void add(int u, int v) {
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int dfn[maxn], low[maxn], dfntmp;
int flag[maxm];
int tot;
int num[maxn];
int root;
int son;
void tarjan(int now) {
dfn[now] = low[now] = ++dfntmp;
for (int i = head[now]; ~i; i = edge[i].next) {
// if(flag[i]) continue;
// flag[i] = flag[i^1] = 1;
int to = edge[i].to;
if (!dfn[to]) {
tarjan(to);
low[now] = min(low[now], low[to]);
if(low[to] >= dfn[now]){
if(now == root) son++;
else num[now]++;
}
} else low[now] = min(low[now], dfn[to]);
}
}
void init(void){
memset(head, -1, sizeof(head));
cnt = -1;
tot = 0;
dfntmp = 0;
son = 0;
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(dfn));
memset(num, 0, sizeof(num));
memset(flag, 0, sizeof(flag));
}
int main(void) {
int u, v;
int Case = 0;
while(scanf("%d", &u) && u){
int n = 0;
if(Case) puts("");
init();
Case++;
printf("Network #%d\n", Case);
scanf("%d", &v);
add(u, v);
add(v, u);
n = max(n, max(u, v));
while(scanf("%d", &u) && u){
scanf("%d", &v);
add(u, v);
add(v, u);
n = max(n, max(u, v));
}
root = 1;
tarjan(1);
if(son > 1) num[1] = son-1;
int check = 0;
for(int i = 1;i <= n;i++){
if(num[i] > 0){
check = 1;
printf(" SPF node %d leaves %d subnets\n", i, num[i]+1);
}
}
if(!check) printf(" No SPF nodes\n");
}
return 0;
}

网络流

dinic

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
71
72
73
struct flownode{
int to, next;
ll w;
};
struct MaxFlow{
private:
#define ll long long
#define MAXN 205
#define MAXM (MAXN * MAXN * 2)
flownode edge[MAXM];
int head[MAXN], cnt;
int deep[MAXN];
ll inf = 0x3f3f3f3f3f3f3f3f;
std::queue<int> q;
public:
int st, ed;
MaxFlow(int st, int ed): st(st), ed(ed){
memset(head, -1, sizeof(head));
cnt = -1;
}
void add(int u, int v, ll w){
addedge(u, v, w);
addedge(v, u, 0);
}
void addedge(int u, int v, ll w){
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
int bfs(void){
memset(deep, 0, sizeof(deep));
q.push(st);
deep[st] = 1;
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = head[now]; ~i;i = edge[i].next){
int to = edge[i].to;
if(edge[i].w && !deep[to]){
deep[to] = deep[now] + 1;
q.push(to);
}
}
}
return deep[ed] != 0;
}
ll dfs(int now, ll fl){
if(now == ed) return fl;
ll f = 0;
for(int i = head[now];~i;i = edge[i].next){
int to = edge[i].to;
if(edge[i].w && deep[to] == deep[now] + 1){
int x = dfs(to, min(fl, edge[i].w));
edge[i].w -= x;
edge[i ^ 1].w += x;
f += x;
fl -= x;
}
}
if(!f) deep[now] = -1;
return f;
}

// 返回最大流
ll Maxflow(void){
ll ans = 0;
while(bfs()){
ans += dfs(st, inf);
}
return ans;
}
};

费用流

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
71
struct mcmfnode{
int to, next;
long long w, c;
};
#define MAXN 5005
#define MAXM 100004
int head[MAXN], cnt;
mcmfnode edge[MAXM];
long long dis[MAXN], flow[MAXN];
int pre[MAXN], vis[MAXN];
struct MCMF{
private:
int st, ed;
long long inf = 0x3f3f3f3f3f3f3f;
std::queue<int> q;
void addedge(int u, int v, long long w, long long c){
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
edge[cnt].w = w;
edge[cnt].c = c;
}
public:
MCMF(int st, int ed): st(st), ed(ed){
memset(head, -1, sizeof(head));
cnt = -1;
}
void add(int u, int v, long long w, long long c){
addedge(u, v, w, c);
addedge(v, u, 0, -c);
}
long long spfa(void){
memset(dis, 0x3f, sizeof(dis));
memset(pre, -1, sizeof(pre));
q.push(st);
dis[st] = 0;
flow[st] = inf;
while(!q.empty()){
int now = q.front();
q.pop();
vis[now] = 0;
for(int i = head[now];i != -1;i = edge[i].next){
int to = edge[i].to;
if(edge[i].w && dis[to] > dis[now] + edge[i].c){
dis[to] = dis[now] + edge[i].c;
pre[to] = i;
flow[to] = std::min(flow[now], edge[i].w);
if(!vis[to]){
vis[to] = 1;
q.push(to);
}
}
}
}
return pre[ed] != -1;
}

// 返回最大流 和 最小费用流
std::pair<long long, long long> mcmf(void){
long long maxflow = 0, ans = 0;
while(spfa()){
maxflow += flow[ed];
ans += flow[ed] * dis[ed];
for(int i = pre[ed];i != -1;i = pre[edge[i^1].to]){
edge[i].w -= flow[ed];
edge[i ^ 1].w += flow[ed];
}
}
return {maxflow, ans};
}
};

无源汇上下界最大流

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
struct node{
int to, next;
int w;
int fl;
}edge[maxm << 1];
int head[maxn], cnt;
void add(int u, int v, int w, int fl){
// cout<<u<<" "<<v<<" "<<w<<endl;
edge[++cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt; edge[cnt].fl = fl;
edge[++cnt].to = u; edge[cnt].w = 0; edge[cnt].next = head[v]; head[v] = cnt; edge[cnt].fl = fl;
}
int depth[maxn];
int st, ed;
int bfs(void){
queue<int> q;
memset(depth, 0, sizeof(depth));
q.push(st);
depth[st] = 1;
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = head[now];i != -1;i = edge[i].next){
int to = edge[i].to;
if(depth[to] == 0 && edge[i].w > 0){
depth[to] = depth[now] + 1;
q.push(to);
}
}
}
return depth[ed] != 0;
}
int dfs(int now, int fl){
if(now == ed) return fl;
int f = 0;
for(int i = head[now];i != -1;i = edge[i].next){
int to = edge[i].to;
if(edge[i].w > 0 && depth[to] == depth[now] + 1){
int x = dfs(to, min(fl, edge[i].w));
f += x;
fl -= x;
edge[i].w -= x;
edge[i ^ 1].w += x;
}
}
if(f == 0) depth[now] = 0;
return f;
}
int dinic(void){
int ans = 0;
while(bfs()) ans += dfs(st, inf);
return ans;
}
int in[maxn], out[maxn];
void solve(void){
memset(head, -1, sizeof(head));
cnt = -1;
int n, m;
cin>>n>>m;
st = 0;
ed = n + 1;
for(int i = 1;i <= m;i++){
int u, v, fl, fr;
cin>>u>>v>>fl>>fr;
add(u, v, fr - fl, fl);
out[u] += fl;
in[v] += fl;
}
int sum = 0;
for(int i = 1;i <= n;i++){
if(in[i] > out[i]){
add(st, i, in[i] - out[i], 0);
sum += in[i] - out[i];
}
if(in[i] < out[i]){
add(i, ed, out[i] - in[i], 0);
}
}
if(dinic() == sum){
cout<<"YES"<<endl;
for(int i = 0;i < m * 2;i += 2){
cout<<edge[i ^ 1].w+edge[i].fl<<endl;
}
}else{
cout<<"NO"<<endl;
}
}

有源汇上下界最大流

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
struct node{
int to, next;
int w;
int fl;
}edge[maxm << 1];
int head[maxn], cnt;
void add(int u, int v, int w, int fl){
// cout<<u<<" "<<v<<" "<<w<<endl;
edge[++cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt; edge[cnt].fl = fl;
edge[++cnt].to = u; edge[cnt].w = 0; edge[cnt].next = head[v]; head[v] = cnt; edge[cnt].fl = fl;
}
int depth[maxn];
int st, ed;
int bfs(void){
queue<int> q;
memset(depth, 0, sizeof(depth));
q.push(st);
depth[st] = 1;
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = head[now];i != -1;i = edge[i].next){
int to = edge[i].to;
if(depth[to] == 0 && edge[i].w > 0){
depth[to] = depth[now] + 1;
q.push(to);
}
}
}
return depth[ed] != 0;
}
int dfs(int now, int fl){
if(now == ed) return fl;
int f = 0;
for(int i = head[now];i != -1;i = edge[i].next){
int to = edge[i].to;
if(edge[i].w > 0 && depth[to] == depth[now] + 1){
int x = dfs(to, min(fl, edge[i].w));
f += x;
fl -= x;
edge[i].w -= x;
edge[i ^ 1].w += x;
}
}
if(f == 0) depth[now] = 0;
return f;
}
int dinic(void){
int ans = 0;
while(bfs()) ans += dfs(st, inf);
return ans;
}
int in[maxn], out[maxn];
void solve(void){
memset(head, -1, sizeof(head));
cnt = -1;
int n, m, s, t;
cin>>n>>m>>s>>t;
st = 0;
ed = n + 1;
for(int i = 1;i <= m;i++){
int u, v, fl, fr;
cin>>u>>v>>fl>>fr;
add(u, v, fr - fl, fl);
out[u] += fl;
in[v] += fl;
}
int sum = 0;
for(int i = 1;i <= n;i++){
if(in[i] > out[i]){
add(st, i, in[i] - out[i], 0);
sum += in[i] - out[i];
}
if(in[i] < out[i]){
add(i, ed, out[i] - in[i], 0);
}
}
add(t, s, inf, 0);
if(dinic() == sum){
int res = edge[cnt].w;
edge[cnt-1].w = edge[cnt].w = 0;
st = s;ed = t;
res+=dinic();
cout<<res<<endl;
}else{
cout<<"No Solution"<<endl;
}
}

最大团

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
71
72
73
74
int n,m;
bool G[N][N];
int cnt[N];//cnt[i]为>=i的最大团点数
int group[N];//最大团的点
int vis[N];//记录点的位置
int res;//最大团的数目
bool dfs(int pos,int num){//num为当前独立集中的点数
for(int i=pos+1;i<=n;i++){
if(cnt[i]+num<=res)//剪枝,若取i但cnt[i]+已经取了的点数仍<ans
return false;

if(G[pos][i]){//与当前团中元素比较,取Non-N(i)
int j;
for(j=0;j<num;j++)
if(!G[i][vis[j]])
break;
if(j==num){//若为空,则皆与i相邻,则此时将i加入到最大团中
vis[num]=i;
if(dfs(i,num+1))
return true;
}
}
}

if(num>res){//每添加一个点最多使最大团数+1,后面的搜索就没有意义了
for(int i=0;i<num;i++)//最大团的元素
group[i]=vis[i];
res=num;//最大团中点的数目
return true;
}
return false;
}
void maxClique(){
res=-1;
for(int i=n;i>0;i--){//枚举所有点
vis[0]=i;
dfs(i,1);
cnt[i]=res;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(G,0,sizeof(G));

scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
G[x][y]=1;
G[y][x]=1;
}

//建立反图
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
G[i][j]=0;
else
G[i][j]^=1;
}
}
maxClique();

if(res<0)
res=0;
printf("%d\n",res);//最大团的个数
for(int i=0;i<res;i++)//最大团中的顶点
printf("%d ",group[i]);
printf("\n");
}
return 0;
}

2-SAT

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
71
72
73
74
75
76
77
void solve(void){
int n, m;
cin>>n>>m;

vector<int> G[n * 2];

for(int k = 0;k < m;k++){
int a, va, b, vb;
cin>>a>>va>>b>>vb;
a--;
b--;
if(va == 1 && vb == 1){
G[a + n].push_back(b); // a为假b必为真
G[b + n].push_back(a); // b为假a必为真
}
if(va == 1 && vb == 0){
G[a + n].push_back(b + n); // a为假b必为假
G[b].push_back(a); //b为真a必为假
}
if(va == 0 && vb == 1){
G[a].push_back(b); // a为真b必为假
G[b + n].push_back(a + n); // b为假a必为假
}
if(va == 0 && vb == 0){
G[a].push_back(b + n); // a为真b必为假
G[b].push_back(a + n); // b为真a必为假
}
}

vector<int> dfn(n * 2), low(n * 2);
vector<int> id(n * 2), vis(n * 2);
int dfntmp = 0;
stack<int> s;
int cnt = 0;

function<void(int)> tarjan = [&](int now){
dfn[now] = low[now] = ++dfntmp;
s.push(now);
vis[now] = 1;
for(int to : G[now]){
if(!dfn[to]){
tarjan(to);
low[now] = min(low[now], low[to]);
}else if(vis[to]){
low[now] = min(low[now], dfn[to]);
}
}
if(dfn[now] == low[now]){
int x;
cnt++;
do{
x = s.top();
s.pop();
id[x] = cnt;
vis[x] = 0;
}while(x != now);
}
};

for(int i = 0;i < n * 2;i++) if(!dfn[i]) tarjan(i);

for(int i = 0;i < n;i++){
if(id[i] == id[i + n]){ // 冲突
cout<<"IMPOSSIBLE"<<endl;
return;
}
}

cout<<"POSSIBLE"<<endl;
for(int i = 0;i < n;i++){
if(id[i] < id[i + n]){ // 拓扑序小的能推到拓扑序大的节点 tarjan为逆拓扑序
cout<<1<<" ";
}else{
cout<<0<<" ";
}
}
}

krusral重构树

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
int id[maxn];
int find(int p){
if(p == id[p]) return p;
return id[p] = find(id[p]);
}
void init(int n){
for(int i = 1;i <= n;i++) id[i] = i;
}
struct node{
int to, next;
}edge[maxm];
int head[maxn], cnt;
void add(int u, int v){
// cout<<"!"<<u<<" "<<v<<endl;
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int fa[maxn][20], depth[maxn];
void dfs(int now, int fath){
depth[now] = depth[fath] + 1;
fa[now][0] = fath;
for(int i = 1;i < 20;i++) fa[now][i] = fa[fa[now][i-1]][i-1];
for(int i = head[now];i;i = edge[i].next){
int to = edge[i].to;
if(to == fath) continue;
dfs(to, now);
}
}
int lca(int u, int v){
if(depth[u] < depth[v]) swap(u, v);
for(int i = 19;i >= 0;i--){
if(depth[u] - (1 << i) >= depth[v]) u = fa[u][i];
}
if(u == v) return u;
for(int i = 19;i >= 0;i--){
if(fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
struct Node{
int l, r, f;
}tr[maxn << 4];
void build(int p, int l, int r){
tr[p].l = l;tr[p].r = r;
if(l == r){
tr[p].f = l;
return;
}
int mid = (l + r) / 2;
build(p<<1, l, mid);
build(p<<1|1, mid + 1, r);
tr[p].f = lca(tr[p<<1].f, tr[p<<1|1].f);
// cout<<"?"<<l<<" "<<r<<" "<<tr[p].f<<endl;
}
int query(int p, int l, int r){
if(tr[p].l >= l && tr[p].r <= r){
return tr[p].f;
}
int f = -1;
int mid = (tr[p].l + tr[p].r) / 2;
if(l <= mid) f = query(p << 1, l, r);
if(r >= mid+1){
if(f == -1) f = query(p << 1 | 1, l, r);
else f = lca(f, query(p << 1 | 1, l, r));
}
return f;
}
int ans[maxn<<1];
void solve(void){
memset(head, 0, sizeof(head));
cnt = 0;
int n, m, q;
cin>>n>>m>>q;
init(n << 1);
int now = n;
for(int i = 1;i <= m;i++){
int u, v;
cin>>u>>v;
if(find(u) == find(v)) continue;
now++;
add(now, find(u));
add(now, find(v));
ans[now] = i;
id[find(u)] = now;
id[find(v)] = now;
}
dfs(now, 0);
build(1, 1, n);
while(q--){
int l, r;
cin>>l>>r;
if(l == r) cout<<0<<" ";
else cout<<ans[query(1, l, r)]<<" ";
}
cout<<endl;
}

数论

gcd

1
2
3
4
5
6
inline ll gcd(ll a, ll b){
if (b == 0)
return a;
else
return gcd(b, a % b);
}

欧拉筛

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const int N = 200000;
int isprime[N/3] = {0},num_prime = 0;//质数数组,质数数量
bool isNotPrime[N] = {1, 1};
inline void prime(void){
for(int i = 2 ; i < N ; i ++){
if(!isNotPrime[i])
isprime[num_prime++]=i;
for(int j = 0 ; j < num_prime && i * isprime[j] < N; j ++){
isNotPrime[i * isprime[j]] = 1;
if(!(i % isprime[j]))
break;
}
}
}

莫筛

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const int N = 200000;   
int mu[N], sumu[N];//莫筛,莫筛前缀和
int isprime[N/3] = {0},num_prime = 0;
int isNotPrime[N] = {1, 1};
inline void mobius(void){
sumu[1] = mu[1] = 1;
for(int i = 2 ; i < N ; i ++){
if(! isNotPrime[i]){
isprime[num_prime ++]=i;
mu[i] = -1;
}
for(int j = 0 ; j < num_prime && i * isprime[j] < N ; j ++){
isNotPrime[i * isprime[j]] = 1;
if( !(i % isprime[j] ) ) break;
mu[isprime[j] * i] = -mu[i];
}
}
for(int i = 2;i < N;i++) sumu[i] = sumu[i-1] + mu[i];
}

欧拉函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const int N = 200000;
int isprime[N/3] = {0},num_prime = 0;//质数数组,质数数量
int phi[N];//欧拉函数
bool isNotPrime[N] = {1, 1};
inline void Eular(void){
phi[1] = 1;
for(int i = 2; i < N; i++){
if(!isNotPrime[i]){
isprime[num_prime++]=i;
phi[i] = i - 1;
}
for(int j = 0; j < num_prime && i * isprime[j] < N; j++){
isNotPrime[i * isprime[j]] = 1;
if(!(i % isprime[j])){
phi[i * isprime[j]] = phi[i] * isprime[j];
break;
}else
phi[i * isprime[j]] = phi[i] * (isprime[j] - 1);
}
}
}

求最小因子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const int maxn = 1e7+5;
int isprime[maxn/3] = {0},num_prime = 0;
int MinFactor[maxn];
inline void FindMinFactor(int n){
MinFactor[1] = 1;
for(int i = 2; i < n; i++){
if(!MinFactor[i]){
isprime[num_prime++]=i;
MinFactor[i] = i;
}
for(int j = 0; i * isprime[j] < n && j < num_prime; j++){
Minfactor[i * isprime[j]] = isprime[j];
if(!(i % isprime[j]))
break;
}
}
}

组合数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const int maxn = 200000 + 5;
const int mod = (int)1e9 + 7;
ll F[maxn], Finv[maxn], inv[maxn];//F是阶乘,Finv是逆元的阶乘
inline void comb_init(){
inv[1] = 1;
for(ll i = 2; i < maxn; i ++){
inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod;
}
F[0] = Finv[0] = 1;
for(ll i = 1; i < maxn; i ++){
F[i] = F[i-1] * 1ll * i % mod;
Finv[i] = Finv[i-1] * 1ll * inv[i] % mod;
}
}
inline ll comb(ll n, ll m){//comb(n, m)就是C(n, m)
if(m < 0 || m > n) return 0;
return F[n] * 1ll * Finv[n - m] % mod * Finv[m] % mod;
}

大数除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
inline int Large_Div(char Dividend[maxn], ll Divisor){
ll ans = 0;
int jd = 0;
if(Divisor < 0) {//除去除数的负号,标记
Divisor = -Divisor;
jd = 1;
}
if(Divisor == 0) return 0;
ll len = strlen(Dividend);
ll now = 0;
for(ll i = 0;i < len;i++){
if(Dividend[i] == '-') continue;//除去被除数的负号
now = now * 10 + (Dividend[i] - '0');
ans += now / Divisor;
now %= Divisor;
}
if(Dividend[0] == '0') return -1;
if(jd ^ (Dividend[0] == '-')) ans = -ans;//如果有一个是负数,结果为负
if(now == 0) return ans;
else return 0;
}

快速幂

1
2
3
4
5
6
7
8
9
10
11
inline ll PowerMod(ll a, ll b, ll c){
ll ans = 1;
a = a % c;
while(b>0){
if(b % 2 == 1)
ans = ((ans % c) * (a % c)) % c;
b = b/2;
a = (a * a) % c;
}
return ans;
}

矩阵快速幂

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
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
#define int ll
const int maxn = 105;
const ll mod = 1e9 + 7;
struct Mat{
ll a[maxn][maxn];
Mat(){
memset(a, 0, sizeof(a));
}
inline void build(){
for(int i = 1;i < maxn;i++) a[i][i] = 1;
}
};
ll n, k;
Mat operator *(const Mat &x, const Mat &y){
Mat z;
for(int k = 1;k <= n;k++){
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
}
}
}
return z;
}
inline Mat QuickMod(Mat now, int k){
Mat ans;
ans.build();
while(k){
if(k & 1) ans = ans * now;
now = now * now;
k >>= 1;
}
return ans;
}
signed main(void){
scanf("%lld %lld",&n, &k);
Mat ans, a;
a.build();
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
scanf("%lld", &a.a[i][j]);
}
}
ans = QuickMod(a, k);
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
printf("%lld ",ans.a[i][j]);
}
printf("\n");
}
return 0;
}

三分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
double f(double x){
//something
}

const double eps=1e-8;
double sanfen(double l, double r){
double mid,midr,ans;
while (fabs(r-l)>eps) {
mid=(l+r)/2;
midr=(mid+r)/2;
if(f(mid) < f(midr)) l=mid; else r=midr; //求最大值
}
ans=f(l);
return ans;
}

矩阵

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const int mod = 1e9+7;
struct Mat{
#define MAX_MAT 2
ll A[MAX_MAT][MAX_MAT << 1];
ll a[MAX_MAT][MAX_MAT];
Mat(){
for (int i = 0; i < MAX_MAT; ++i)
for (int j = 0; j < MAX_MAT; ++j)
a[i][j] = 0;
for (int i = 0; i < MAX_MAT; ++i)
a[i][i] = 1;
}
Mat(ll a1, ll a2, ll a3, ll a4){
a[0][0] = a1;
a[0][1] = a2;
a[1][0] = a3;
a[1][1] = a4;
}
void row_minus(int i, int j, ll k){
for (int l = 0; l < 2 * MAX_MAT; ++l){
A[i][l] = (A[i][l] - A[j][l] * k % mod) % mod;
if (A[i][l] < 0)A[i][l] += mod;
}
}
void row_multiplies(int j, ll k){
for (int i = 0; i < 2 * MAX_MAT; ++i){
A[j][i] = (A[j][i] * k) % mod;
}
}
void row_swap(int i, int j){
for (int l = 0; l < 2 * MAX_MAT; ++l)
swap(A[i][l], A[j][l]);
}
ll get_inv(ll x)
{
return ksm(x, mod - 2, mod);
}
Mat getinv(void)
{
memset(A, 0, sizeof(A));
for (int i = 0; i < MAX_MAT; ++i){
for (int j = 0; j < MAX_MAT; ++j){
A[i][j] = a[i][j];
A[i][MAX_MAT + j] = i == j;
}
}
for (int i = 0; i < MAX_MAT; ++i){
if (!A[i][i]){
for (int j = i + 1; j < MAX_MAT; ++j){
if (A[j][i]){
row_swap(i, j);
break;
}
}
}
row_multiplies(i, get_inv(A[i][i]));
for (int j = i + 1; j < MAX_MAT; ++j)
row_minus(j, i, A[j][i]);
}
for (int i = MAX_MAT - 1; i >= 0; --i)
for (int j = i - 1; j >= 0; --j)
row_minus(j, i, A[j][i]);
Mat res;
for (int i = 0; i < MAX_MAT; ++i)
for (int j = 0; j < MAX_MAT; ++j)
res.a[i][j] = A[i][MAX_MAT + j];
return res;
}
Mat operator * (const Mat y) const{
Mat c;
for (int i = 0; i < MAX_MAT; ++i)
for (int j = 0; j < MAX_MAT; ++j)
c.a[i][j] = 0;
for (int i = 0; i < MAX_MAT; ++i)
for (int j = 0; j < MAX_MAT; ++j)
for (int k = 0; k < MAX_MAT; ++k)
c.a[i][j] = (c.a[i][j] + a[i][k] * y.a[k][j] % mod) % mod;
return c;
}
void print(void){
for(int i = 0;i < MAX_MAT;i++){
for(int j = 0;j < MAX_MAT;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
cout<<"******"<<endl;
}
};

数据结构

线段树

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
struct tnode{
int l, r;
int len;
ll sum;
ll lazy;
};
struct SegmentTree{
private:
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)
#define md(p) ((tr[p].l + tr[p].r) >> 1)
vector<tnode> tr;
vector<ll> a;
void pushup(int p){
tr[p].sum = tr[ls(p)].sum + tr[rs(p)].sum;
}
void pushdown(int p){
if(tr[p].lazy){
tr[ls(p)].lazy += tr[p].lazy;
tr[rs(p)].lazy += tr[p].lazy;
tr[ls(p)].sum += tr[ls(p)].len * tr[p].lazy;
tr[rs(p)].sum += tr[rs(p)].len * tr[p].lazy;
tr[p].lazy = 0;
}
}
void build(int p, int l, int r){
tr[p].l = l;
tr[p].r = r;
tr[p].len = tr[p].r - tr[p].l + 1;
tr[p].lazy = 0;
if(l == r){
tr[p].sum = a[l];
return;
}
int mid = md(p);
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
}
public:
SegmentTree(int n, vector<ll> a): tr((n + 1) * 4), a(a){
build(1, 1, n);
}
void update(int p,int l, int r, ll num){
if(tr[p].l >= l && tr[p].r <= r){
tr[p].sum += num * tr[p].len;
tr[p].lazy += num;
return;
}
pushdown(p);
int mid = md(p);
if(l <= mid) update(ls(p), l, r, num);
if(r > mid) update(rs(p), l, r, num);
pushup(p);
}
ll query(int p, int l, int r){
if(tr[p].l >= l && tr[p].r <= r) return tr[p].sum;
pushdown(p);
int mid = md(p);
ll ans = 0;
if(l <= mid) ans += query(ls(p), l, r);
if(r > mid) ans += query(rs(p), l, r);
return ans;
}
};

ST表

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
struct RMQ{
private:
std::vector<long long> num;
std::vector<int> lg2;
std::vector<std::vector<int> > mx, mn;
int n;
public:
RMQ(int n, std::vector<long long> a) : n(n), lg2(n+1), num(a), mx(n + 1), mn(n + 1) {
lg2[1] = 0;
for(int i = 2;i <= n;i++) lg2[i] = lg2[i/2] + 1;
for(int i = 1;i <= n;i++){
mx[i].resize(lg2[n] + 1);
mn[i].resize(lg2[n] + 1);
mx[i][0] = a[i];
mn[i][0] = a[i];
}
for(int j = 1;j <= lg2[n];j++){
for(int i = 1;i <= n;i++){
mx[i][j] = std::max(mx[i][j-1], mx[std::min(i + (1 << (j - 1)), n)][j-1]);
mn[i][j] = std::min(mn[i][j-1], mn[std::min(i + (1 << (j - 1)), n)][j-1]);
}
}
}
long long qmax(int l, int r){
int tmp = lg2[r - l + 1];
return std::max(mx[l][tmp], mx[r - (1 << tmp) + 1][tmp]);
}
long long qmin(int l, int r){
int tmp = lg2[r - l + 1];
return std::min(mn[l][tmp], mn[r - (1 << tmp) + 1][tmp]);
}
};

Trie树

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
#include<iostream>
using namespace std;
const int maxn = 1e5;
struct node{
int son[26];
}trie[maxn];
int cnt, root[maxn];
void insert(string str, int id){
int now = 0;
int l = str.length();
for(int i = 0;i < l;i++){
if(trie[now].son[str[i]-'a'] == 0){
trie[now].son[str[i]-'a'] = ++cnt;//动态开点
}
now = trie[now].son[str[i] - 'a'];
}
root[now] = id;
}
int search(string str){
int now = 0;
int l = str.length();
for(int i = 0;i < l;i++){
now = trie[now].son[str[i] - 'a'];
if(now == 0) return 0;
}
return root[now];
}
int main(void){
int n;
cin>>n;
string str;
for(int i = 1;i <= n;i++){
cin>>str;
insert(str,i);
}
cin>>n;
for(int i = 1;i <= n;i++){
cin>>str;
cout<<search(str)<<endl;
}
return 0;
}

主席树

单点修改主席树

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
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 2e5 + 5;
struct Node{
int l, r, sum;
}hjt[maxn*40];
int cnt, root[maxn];
int num[maxn];
vector<int> v;

int getid(int x){
return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
}

void insert(int l, int r, int pre, int &now, int p){
hjt[++cnt] = hjt[pre];
now = cnt;
hjt[now].sum++;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid){
insert(l, mid, hjt[pre].l, hjt[now].l, p);
}else{
insert(mid + 1, r, hjt[pre].r, hjt[now].r, p);
}
}

int query(int l, int r, int L, int R, int k){
if(l == r) return l;
int mid = (l + r) >> 1;
int temp = hjt[hjt[R].l].sum - hjt[hjt[L].l].sum;
if(k <= temp){
return query(l, mid, hjt[L].l, hjt[R].l, k);
}else{
return query(mid + 1, r, hjt[L].r, hjt[R].r, k - temp);
}
}

int main(void){
int n, m;
cin>>n>>m;
for(int i = 1;i <= n;i++){
cin>>num[i];
v.push_back(num[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(),v.end()), v.end());
for(int i = 1;i <= n;i++){

insert(1, n, root[i-1], root[i], getid(num[i]));
}
for(int i = 1;i <= m;i++){
int l, r, k;
cin>>l>>r>>k;
cout<<v[query(1, n, root[l-1], root[r], k) - 1]<<endl;
}
return 0;
}

区间修改主席树(标记永久化)

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
#define md(p) ((tr[p].l + tr[p].r) >> 1)
struct node{
int l, r;
int ls, rs;
ll sum, lazy;
}tr[maxn * 40];
int root[maxn], cnt;
void pushup(int p){
tr[p].sum = tr[tr[p].ls].sum + tr[tr[p].rs].sum;
}
void build(int& p, int l, int r){
p = ++cnt;
tr[p].l = l;
tr[p].r = r;
tr[p].lazy = 0;
if(l == r){
cin>>tr[p].sum;
return;
}
int mid = md(p);
build(tr[p].ls, l, mid);
build(tr[p].rs, mid + 1, r);
pushup(p);
}
void update(int pre, int &p, int l, int r, ll num){
p = ++cnt;
tr[p] = tr[pre];
tr[p].sum += (min(tr[p].r,r)-max(tr[p].l,l)+1) * num;
if(tr[p].l >= l && tr[p].r <= r){
tr[p].lazy += num;
return;
}
int mid = md(p);
if(l <= mid) update(tr[pre].ls, tr[p].ls, l, r, num);
if(r > mid) update(tr[pre].rs, tr[p].rs, l, r, num);
}
ll query(int p, int l, int r, ll lz){
if(tr[p].l >= l && tr[p].r <= r){
return tr[p].sum + lz * (ll)(tr[p].r - tr[p].l + 1);
}
int mid = md(p);
ll ans = 0;
if(l <= mid) ans += query(tr[p].ls, l, r, lz + tr[p].lazy);
if(r > mid) ans += query(tr[p].rs, l, r, lz + tr[p].lazy);
return ans;
}

树状数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Bit{
int a[maxn];
void add(int x){
for(;x < maxn;x += lowbit(x)) a[x] ++;
}
void del(int x){
for(;x < maxn;x += lowbit(x)) a[x] --;
}
int query(int x){
int ans = 0;
for(;x;x -= lowbit(x)) ans += a[x];
return ans;
}
}bit;

dfs序

1
2
3
4
5
6
7
8
9
10
11
12
void dfs(int node,int parent){
NewIdx[NCnt] = node;
InOut[NCnt] = 1;
InIdx[node] = NCnt++;
for(int next=Vertex[node];next;next=Edge[next].next){
int son = Edge[next].to;
if ( son != parent ) dfs(son,node);
}
NewIdx[NCnt] = node;
InOut[NCnt] = -1;
OutIdx[node] = NCnt++;
}

莫队

普通莫队

块:$\frac{n}{\sqrt{m}}$

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
struct node{
int l, r;
int id;
}que[maxn];
int v[maxn], id[maxn];
int cnt[maxn], ans[maxn];
void solve(void){
int n;
scanf("%d", &n);
int m;
scanf("%d", &m);
for(int i = 1;i <= n;i++) scanf("%d", &v[i]);

int blo = (int)n / sqrt(m);
for(int i = 1;i <= n;i++) id[i] = (i - 1) / blo + 1;

for(int i = 1;i <= m;i++){
scanf("%d %d", &que[i].l, &que[i].r);
que[i].id = i;
}

sort(que + 1, que + 1 + m, [&](node a, node b){
if(id[a.l] != id[b.l]) return id[a.l] < id[b.l];
return id[a.l] & 1 ? a.r < b.r : a.r > b.r;
});

int res = 1;
auto add = [&](int now){
if(cnt[now] == 0) res++;
cnt[now]++;
};

auto del = [&](int now){
if(cnt[now] == 1) res--;
cnt[now]--;
};

int i = 1, j = 0;
for(int k = 1;k <= m;k++){
int l = que[k].l, r = que[k].r;
while(i < l) del(v[i ++]);
while(i > l) add(v[-- i]);
while(j < r) add(v[++ j]);
while(j > r) del(v[j --]);
ans[que[k].id] = res;
}
for(int k = 1;k <= m;k++) printf("%d\n", ans[k]);
}

带修莫队

块:$n^\frac{2}{3}$

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
71
72
73
74
75
76
77
78
79
80
81
82
83
struct Que{
int l, r;
int t;
int id;
};
struct CH{
int val, pos;
};
void solve(void){
int n, m;
cin>>n>>m;
vector<int> a(n + 1);
for(int i = 1; i<= n;i++){
cin>>a[i];
}

vector<Que> q(m + 1);
vector<CH> ch(m + 1);
int cntq = 0, cntc = 0;
for(int i = 1;i <= m;i++){
int op;
cin>>op;
if(op == 1){
cntq++;
cin >> q[cntq].l >>q[cntq].r;
q[cntq].t = cntc;
q[cntq].id = cntq;
}else{
++cntc;
cin>>ch[cntc].pos>>ch[cntc].val;
}
}

sort(q.begin() + 1, q.begin() + cntq + 1, [&](Que a, Que b){
if(bl[a.l] != bl[b.l]) return bl[a.l] < bl[b.l];
if(bl[a.r] != bl[b.r]) return bl[a.r] < bl[b.r];
return a.t < b.t;
});

vector<int> count(n + m + 1);
vector<int> num(n + m + 1);

function<void(int)> add = [&](int now){
count[num[now]] --;
num[now]++;
count[num[now]] ++;
};

function<void(int)> del = [&](int now){
count[num[now]] --;
num[now]--;
count[num[now]] ++;
};

function<void(int, int)> che = [&](int i, int j){
if(q[i].l <= ch[j].pos && q[i].r >= ch[j].pos){
del(a[ch[j].pos]);
add(ch[j].val);
}
swap(a[ch[j].pos], ch[j].val);
};

int l = 1, r = 0, t = 0;
vector<int> ans(m + 1);

for(int i = 1;i <= cntq;i++){
int L = q[i].l, R = q[i].r, T = q[i].t;
while(l < L) del(a[l++]);
while(l > L) add(a[--l]);
while(r < R) add(a[++r]);
while(r > R) del(a[r--]);
while(t < T) che(i, ++t);
while(t > T) che(i, t--);

int ret = 1;
while(count[ret]) ret++;
ans[q[i].id] = ret;
}

for(int i = 1;i <= cntq;i++){
cout<<ans[i]<<endl;
}
}

珂朵莉树

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
struct ODT{
private:
struct node{
int l, r;
mutable long long v;
node(int L, int R = -1, long long V = 0): l(L), r(R), v(V){};
bool operator < (const node& oth) const {
return l < oth.l;
}
};
std::vector<std::pair<long long, long long>> vp;
std::set<node> s;
#define ddq std::set<node>::iterator
public:
ODT(){
s.clear();
}
void insert(int l, int r, long long val){
s.insert(node(l, r, val));
}
ddq split(int pos){
ddq it = s.lower_bound(node(pos));
if(it != s.end() && it->l == pos) return it;
--it;
if(pos > it->r) return s.end();
int L = it->l, R = it->r;
long long V = it->v;
s.erase(it);
s.insert(node(L, pos-1, V));
return s.insert(node(pos, R, V)).first;
}
void add(int l, int r, long long val){
ddq itr = split(r + 1), itl = split(l);
for(;itl != itr;itl++){
itl->v += val;
}
}
void change(int l, int r, long long val){
ddq itr = split(r + 1), itl = split(l);
s.erase(itl, itr);
s.insert(node(l, r, val));
}
long long getk(int l, int r, long long k){
ddq itr = split(r + 1), itl = split(l);
vp.clear();
for(;itl != itr;itl++){
vp.push_back({itl->v, itl->r - itl->l + 1});
}
sort(vp.begin(), vp.end());
for(auto now : vp){
k -= now.second;
if(k <= 0) return now.first;
}
return -1;
}
long long sum(int l, int r, long long k, long long mod){
long long ans = 0;
ddq itr = split(r + 1), itl = split(l);
for(;itl != itr;itl++){
ans = (ans + (long long)(itl->r - itl->l + 1) * ksm(itl->v, k, mod)) % mod;
}
return ans;
}
};

splay

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
struct SplayNode{
int s[2];
int p;
int cnt, v;
int size;
int lazy;
SplayNode(){};
SplayNode(int v, int p): v(v), p(p), cnt(1), size(1) {
memset(s, 0, sizeof(s));
}
};
struct Splay{
private:
#define MAXN 200010
int cnt = 0, root = 0;
SplayNode tr[MAXN];
void pushup(int p){
tr[p].size = tr[tr[p].s[0]].size + tr[tr[p].s[1]].size + tr[p].cnt;
}
void rotate(int x){
int y = tr[x].p, z = tr[y].p;
int k = tr[y].s[1] == x;

tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;

tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;

tr[x].s[k ^ 1] = y;
tr[y].p = x;
pushup(y), pushup(x);
}
void splay(int x, int k){
while(tr[x].p != k){
int y = tr[x].p, z = tr[y].p;
if(z != k){
if((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!k) root = x;
}
public:
SplayNode findx(int v){
int u = root;
if(!u) return SplayNode(0, 0);
while(tr[u].s[v > tr[u].v] && v != tr[u].v){
u = tr[u].s[v > tr[u].v];
}
splay(u, 0);
return tr[root];
}
SplayNode insert(int v){
int u = root, p = 0;

while(u && tr[u].v != v){
// std::cout<<"!"<<u<<"\n";
p = u;
u = tr[u].s[v > tr[u].v];
}
if(u){
tr[u].cnt ++;
splay(u, 0);
}else{
u = ++cnt;
if(p) tr[p].s[v > tr[p].v] = u;
tr[u] = SplayNode(v, p);
splay(u, 0);
}
return tr[root];
}
int kth(int k){
int u = root;
while(u){
if(tr[tr[u].s[0]].size >= k) u = tr[u].s[0];
else if(tr[tr[u].s[0]].size + tr[u].cnt >= k) return tr[u].v;
else{
k -= tr[tr[u].s[0]].size + tr[u].cnt;
u = tr[u].s[1];
}
}
return -1;
}
int getrk(int x){
findx(x);
int u = root;
return tr[tr[u].s[0]].size + 1;
}
int next(int x, int f){ //0-prev,1-next
findx(x);
int u = root;
if(tr[u].v > x && f) return u;
if(tr[u].v < x && !f) return u;
u = tr[u].s[f];
while(tr[u].s[f ^ 1]) u = tr[u].s[f ^ 1];
return u;
}
void remove(int x){
int l = next(x, 0);
int r = next(x, 1);
splay(l, 0);
splay(r, l);
int u = tr[r].s[0];
if(tr[u].cnt > 1){
tr[u].cnt--;
splay(u, 0);
}else{
tr[r].s[0] = 0;
}
}
SplayNode getpre(int x){
return tr[next(x, 0)];
}
SplayNode getnext(int x){
return tr[next(x, 1)];
}
};

圆方树

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
struct RSTree{
private:
vector<vector<int> > G;
vector<vector<int> > e;
vector<int> dfn, low;
stack<int> s;
int dfntmp;
int cnt;
int n;

void dfs(int now){
dfn[now] = low[now] = ++dfntmp;
s.push(now);
for(int to : G[now]){
if(!dfn[to]){
dfs(to);
low[now] = min(low[now], low[to]);
if(low[to] == dfn[now]){
e.push_back({});
int x;
do{
x = s.top();
s.pop();
e[x].push_back(cnt);
e[cnt].push_back(x);
}while(x != to);
e[now].push_back(cnt);
e[cnt].push_back(now);
cnt++;
}
} else low[now] = min(low[now], dfn[to]);
}
}
public:
RSTree(int n): n(n), G(n), dfn(n, 0), low(n), e(n), cnt(n), dfntmp(0) {};

void add(int u, int v){
G[u].push_back(v);
G[v].push_back(u);
}

void solve(void){
for(int i = 0;i < n;i++){
if(!dfn[i]) dfs(i);
}
}

vector<int> getdfn(void){
return dfn;
}

vector<vector<int> > getnew(void){
return e;
}

int getcnt(void){
return cnt;
}
};

LCT

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
71
72
73
74
75
76
77
78
79
80
81
82
83
namespace LCT{
const int N = 3e5+5;
#define ls c[x][0]
#define rs c[x][1]
int f[N], c[N][2], v[N], s[N], st[N];
bool r[N];
bool nroot(int x){
return c[f[x]][0] == x || c[f[x]][1] == x;
}

void pushup(int x){
s[x] = s[ls] ^ s[rs] ^ v[x];
}

void pushr(int x){
swap(ls, rs);
r[x] ^= 1;
}

void pushdown(int x){
if(r[x]){
if(ls) pushr(ls);
if(rs) pushr(rs);
r[x] = 0;
}
}

void rotate(int x){
int y = f[x], z = f[y], k = c[y][1] == x, w = c[x][!k];
if(nroot(y)) c[z][c[z][1] == y] = x;c[x][!k] = y;c[y][k] = w;
if(w) f[w] = y;f[y] = x, f[x] = z;
pushup(y);
}

void splay(int x){
int y = x, z = 0;
st[++z] = y;
while(nroot(y)) st[++z] = y = f[y];
while(z) pushdown(st[z--]);
while(nroot(x)){
y = f[x];z = f[y];
if(nroot(y))
rotate((c[y][0] == x) ^ (c[z][0] == y) ? x : y);
rotate(x);
}
pushup(x);
}

void access(int x){
for(int y = 0;x;x = f[y=x])
splay(x), rs = y, pushup(x);
}

void makeroot(int x){
access(x);splay(x);
pushr(x);
}

int findroot(int x){
access(x);splay(x);
while(ls) pushdown(x), x = ls;
splay(x);
return x;
}

void split(int x, int y){
makeroot(x);
access(y);splay(y);
}

void link(int x, int y){
makeroot(x);
if(findroot(y) != x) f[x] = y;
}

void cut(int x, int y){
makeroot(x);
if(findroot(y) == x && f[y] == x && !c[y][0]){
f[y] = c[x][1] = 0;
pushup(x);
}
}
}

线段树合并

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
struct node{
int ls, rs;
int sum, ans;
}tr[5000050];
int root[maxn];
int cnt = 0;
void pushup(int p){
if(tr[tr[p].ls].sum > tr[tr[p].rs].sum){
tr[p].sum = tr[tr[p].ls].sum;
tr[p].ans = tr[tr[p].ls].ans;
}else if(tr[tr[p].ls].sum == tr[tr[p].rs].sum){
tr[p].sum = tr[tr[p].ls].sum;
tr[p].ans = tr[tr[p].ls].ans + tr[tr[p].rs].ans;
}else{
tr[p].sum = tr[tr[p].rs].sum;
tr[p].ans = tr[tr[p].rs].ans;
}
}
void update(int &p, int l, int r, int val){
if(!p) p = ++cnt;
if(l == r){
tr[p].ans = val;
tr[p].sum++;
return;
}
int mid = (l + r) / 2;
if(val <= mid) update(tr[p].ls, l, mid, val);
else update(tr[p].rs, mid + 1, r, val);
pushup(p);
}
int merge(int p, int pre, int l, int r){
if(!p || !pre) return p + pre;
if(l == r){
tr[p].ans = l;
tr[p].sum += tr[pre].sum;
return p;
}
int mid = (l + r) / 2;
tr[p].ls = merge(tr[p].ls, tr[pre].ls, l, mid);
tr[p].rs = merge(tr[p].rs, tr[pre].rs, mid + 1, r);
pushup(p);
return p;
}

其他

快读

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
template <typename T>inline void read(T& x){
T sum = 0, f = 1;
char c=getchar();
while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) {sum=sum*10+c-'0';c=getchar();}
x=sum*f;
}

template<typename T> inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}

inline void read(double &x){
double z=0,t=0;int s=0,f=1;char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-1; if(c=='.') goto readt; c=getchar();}
while (isdigit(c)&&c!='.') {z=z*10+c-'0';c=getchar();}
readt:while (c=='.') c=getchar();
while (isdigit(c)) {t=t*10+c-'0';++s; c=getchar();}
x=(z+t/pow(10,s))*f;
}

inline void write(double x,int k=6){
ll n=pow(10,k + 1);
if (x==0) {putchar('0'),putchar('.');for (int i=1;i<=k;++i) putchar('0');return;}
if (x<0) putchar('-'),x=-x;
ll y=(ll)(x*n)%n;x=(ll)x;
int bit[20], p=0,i;
if(y % 10 >= 5) y = y/10+1;
else y = y/10;
for (;p<k;y/=10) bit[++p]=y%10;
if(y) x++;
write((ll)x),putchar('.');
for (i=p;i>0;i--) putchar(bit[i]+48);
}