#include<bits/stdc++.h>usingnamespace std;constint N =2e5;int n, cnt, root, m, res;int low[N], dfn[N], cut[N];
vector <int> a[N];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s *10+ c -48, c =getchar();return w ?-s : s;}voidtarjan(int x){int flag =0;
low[x]= dfn[x]=++ cnt;for(int i=0;i<a[x].size();++i){int y = a[x][i];if(dfn[y]==0){tarjan(y);
low[x]=min(low[x], low[y]);if(dfn[x]<= low[y]){
flag ++;if(flag >1|| x != root) cut[x]=1;}}else low[x]=min(low[x], dfn[y]);}return;}intmain(void){
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read();
a[x].push_back(y);
a[y].push_back(x);}for(int i=1;i<=n;++i)if(dfn[i]==0) root = i,tarjan(i);for(int i=1;i<=n;++i) res += cut[i];printf("%d\n", res);for(int i=1;i<=n;++i)if(cut[i])printf("%d ", i);return0;}
1.2 割边算法
#include<bits/stdc++.h>usingnamespace std;constint N =5e5;int n, m, tot =1, cnt, k;int Link[N], low[N], dfn[N], B[N *2];
pair<int,int> t[N *2];struct node
{int x, y, next;} e[N *2];voidadd(int x,int y){
e[++ tot]={x, y, Link[x]};
Link[x]= tot;}intread(void){int x;scanf("%d",&x);return x;}voidtarjan(int x,int last){
low[x]= dfn[x]=++ cnt;for(int i=Link[x];i;i=e[i].next){int y = e[i].y;if(dfn[y]==0){tarjan(y, i);
low[x]=min(low[x], low[y]);if(dfn[x]< low[y]) B[i]= B[i ^1]=1;}elseif((i^1)!= last) low[x]=min(low[x], dfn[y]);}return;}intmain(void){freopen("danger.in","r",stdin);freopen("danger.out","w",stdout);
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read();add(x, y);add(y, x);}for(int i=1;i<=n;++i)if(dfn[i]==0)tarjan(i,0);for(int i=2;i<=tot;i+=2)if(B[i]) t[++ k]={min(e[i].x,e[i].y),max(e[i].x,e[i].y)};sort(t+1,t+k+1);for(int i=1;i<=k;++i)printf("%d %d\n", t[i].first, t[i].second);return0;}
1.3 强连通分量
#include<bits/stdc++.h>usingnamespace std;constint N =3e5;int n, m, scc, cnt, top;int low[N], in[N], dfn[N], st[N], col[N], siz[N];
vector <int> a[N];intread(void){int x;scanf("%d",&x);return x;}voidtarjan(int x){
low[x]= dfn[x]=++ cnt;
in[x]=1, st[++ top]= x;for(int i=0;i<a[x].size();++i){int y = a[x][i];if(dfn[y]==0){tarjan(y);
low[x]=min(low[x], low[y]);}elseif(in[y]) low[x]=min(low[x], dfn[y]);}if(low[x]== dfn[x]){int y; scc ++;do y = st[top --], in[y]=0, col[y]= scc, siz[scc]++;while(x != y);}return;}intmain(void){freopen("popular.in","r",stdin);freopen("popular.out","w",stdout);
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read();
a[x].push_back(y);}for(int i=1;i<=n;++i)if(dfn[i]==0)tarjan(i);for(int i=1;i<=n;++i)for(int j=0;j<a[i].size();++j)if(col[i]!= col[a[i][j]]) in[col[i]]++;int Now =0, p =0;for(int i=1;i<=scc;++i)if(in[i]==0) Now ++, p = i;if(Now >1) cout <<0<< endl;else cout << siz[p]<< endl;return0;}
2 最小生成树
2.1 B算法
#include<bits/stdc++.h>usingnamespace std;constint N =3e5;int n, m, res =0;int fa[N], Min[N], p[N];
vector < pair<int,int>> a[N];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}intget(int x){if(fa[x]== x)return x;return fa[x]=get(fa[x]);}intmain(void){
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read(), v =read();
a[x].push_back({y, v});
a[y].push_back({x, v});}for(int i=1;i<=n;++i) fa[i]= i;while(true){int flag =0;for(int i=1;i<=n;++i) Min[i]=1e9;for(int x=1;x<=n;++x){for(int i=0;i<a[x].size();++i){int y = a[x][i].first;int v = a[x][i].second;if(get(x)==get(y))continue;if(v < Min[get(x)]){
Min[get(x)]= v;
p[get(x)]= y;}}}for(int i=1;i<=n;++i){if(get(i)!=get(p[i])&& Min[i]<1e9){
res += Min[i], flag =1;
fa[get(i)]=get(p[i]);}}if(flag ==0)break;}
cout << res << endl;return0;}
2.2 Prim算法
#include<bits/stdc++.h>usingnamespace std;constint N =3e5;int n, m, res;int vis[N], dis[N];
vector < pair<int,int>> a[N];
priority_queue < pair<int,int>> q;intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}voidPrim(void){memset(vis,0,sizeof vis);memset(dis,30,sizeof dis);
q.push({dis[1]=0,1});while(q.size()){int x = q.top().second; q.pop();if(vis[x])continue; vis[x]=1;
res += dis[x];for(int i=0;i<a[x].size();++i){int y = a[x][i].first;int v = a[x][i].second;if(v < dis[y]){
dis[y]= v;
q.push({-dis[y], y});}}}
cout << res << endl;return;}intmain(void){
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read(), v =read();
a[x].push_back({y, v});
a[y].push_back({x, v});}Prim();return0;}
2.3 Kruscal算法
#include<bits/stdc++.h>usingnamespace std;constint N =3e5;intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}int n, m, res =0;int fa[N];struct node {int x, y, v;friendbooloperator<(node p1, node p2){return p1.v < p2.v;}} e[N];intget(int x){if(fa[x]== x)return x;return fa[x]=get(fa[x]);}intmain(void){
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read(), v =read();
e[i]={x, y, v};}for(int i=1;i<=n;++i) fa[i]= i;sort(e+1, e+m+1);for(int i=1;i<=m;++i){int x = e[i].x, y = e[i].y;if(get(x)==get(y))continue;
res += e[i].v;
fa[get(x)]=get(y);}
cout << res << endl;return0;}
#include<bits/stdc++.h>usingnamespace std;constint N =3e5;int n, m;int vis[N], dis[N], cnt[N];
vector < pair <int,int>> a[N];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}voidSPFA(void){
queue <int> q;memset(vis,0,sizeof vis);memset(dis,30,sizeof dis);
q.push(dis[0]=0), vis[0]=1;while(q.size()){int x = q.front(); q.pop();
vis[x]=0;if(++ cnt[x]>100){puts("NO");exit(0);}for(int i=0;i<a[x].size();++i){int y = a[x][i].first;int v = a[x][i].second;if(dis[x]+ v < dis[y]){
dis[y]= dis[x]+ v;if(vis[y]==0) q.push(y), vis[y]=1;}}}for(int i=1;i<=n;++i)printf("%d\n", dis[i]);return;}intmain(void){
n =read(), m =read();for(int i=1;i<=m;++i){int x =read(), y =read(), v =read();
a[y].push_back({x, v});}for(int i=1;i<=n;++i) a[0].push_back({i,0});SPFA();return0;}
4 ST表
#include<bits/stdc++.h>usingnamespace std;constint N =2e5;int n, m;int a[N], f[N][30];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}intmain(void){
n =read(), m =read();for(int i=1;i<=n;++i){
a[i]=read();
f[i][0]= a[i];}for(int j=1;j<=log2(n);++j)for(int i=1;i<=n-(1<<j)+1;++i)
f[i][j]=max(f[i][j-1], f[i+(1<<j-1)][j-1]);while(m --){int l =read(), r =read();int k =log2(r - l +1);printf("%d\n",max(f[l][k], f[r-(1<<k)+1][k]));}return0;}
5 莫队
#include<bits/stdc++.h>usingnamespace std;constint N =2e6;int n, T, m, ans;int c[N], cnt[N], res[N];struct node {int l, r, bel, id;friendbooloperator<(node p1, node p2){if(p1.bel == p2.bel)return p1.r < p2.r;return p1.bel < p2.bel;}} a[N];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}voidadd(int x){
cnt[c[x]]++;if(cnt[c[x]]==1) ans ++;}voiddel(int x){
cnt[c[x]]--;if(cnt[c[x]]==0) ans --;}intmain(void){
T =sqrt(n =read());for(int i=1;i<=n;++i) c[i]=read();
m =read();for(int i=1;i<=m;++i){
a[i].l =read();
a[i].r =read();
a[i].bel =(a[i].l -1)/ T;
a[i].id = i;}sort(a+1, a+m+1);int l =1, r =0;for(int i=1;i<=m;++i){while(l > a[i].l)add(-- l);while(r < a[i].r)add(++ r);while(l < a[i].l)del(l ++);while(r > a[i].r)del(r --);
res[a[i].id]= ans;}for(int i=1;i<=m;++i)printf("%d\n", res[i]);return0;}
6 Dsu on Tree
#include<bits/stdc++.h>#define int long longusingnamespace std;constint N =5e5;int n, Max;longlong sum =0;int siz[N], son[N], cnt[N], res[N], c[N];
vector <int> a[N];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}voidDfs(int x,int fa){
siz[x]=1;for(int i=0;i<a[x].size();++i){int y = a[x][i];if(y == fa)continue;Dfs(y, x);
siz[x]+= siz[y];if(siz[y]> siz[son[x]]) son[x]= y;}return;}voidModify(int x,int fa,int add,int Son){
cnt[c[x]]+= add;if(cnt[c[x]]> Max) Max = cnt[sum = c[x]];elseif(cnt[c[x]]== Max) sum += c[x];for(int i=0;i<a[x].size();++i){int y = a[x][i];if(y == fa || y == Son)continue;Modify(y, x, add,0);}return;}voidDsu(int x,int fa,int flag){for(int i=0;i<a[x].size();++i){int y = a[x][i];if(y == fa || y == son[x])continue;Dsu(y, x,0);}if(son[x])Dsu(son[x], x,1);Modify(x, fa,1, son[x]);
res[x]= sum;if(flag ==0)Modify(x, fa,-1,0), sum = Max =0;return;}signedmain(void){
n =read();for(int i=1;i<=n;++i) c[i]=read();for(int i=1;i<n;++i){int x =read(), y =read();
a[x].push_back(y);
a[y].push_back(x);}Dfs(1,0);Dsu(1,0,1);for(int i=1;i<=n;++i)printf("%lld ", res[i]);return0;}
7 线性筛
#include<bits/stdc++.h>usingnamespace std;constint N =2e5;int n, k, cnt;int prime[50000000], vis[100000010];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}intmain(void){
n =read(), k =read();for(int i=2;i<=n;++i){if(vis[i]==0) prime[++ cnt]= i;for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
vis[i*prime[j]]=1;if(i % prime[j]==0)break;}}while(k --)printf("%d\n", prime[read()]);return0;}
8 欧拉函数
#include<bits/stdc++.h>usingnamespace std;constint N =2e5;int n, k, cnt;int prime[50000000], vis[100000010], phi[100000];intread(void){int s =0, w =0;char c =getchar();while(!isdigit(c)) w |= c =='-', c =getchar();while(isdigit(c)) s = s*10+c-48, c =getchar();return w ?-s : s;}intmain(void){
n =read(), k =read();for(int i=2;i<=n;++i){if(vis[i]==0) prime[++ cnt]= i, phi[i]= i -1;for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
vis[i*prime[j]]=1;if(i % prime[j]==0){ phi[i*prime[j]]= phi[i]* prime[j];break;}if(i % prime[j]!=0) phi[i * prime[j]]= phi[i]*(prime[j]-1);}}for(int i=1;i<=30;++i) cout << i <<':'<< phi[i]<< endl;return0;}
9 线性求逆元
#include<bits/stdc++.h>usingnamespace std;constint N =5e6;int n, P;int inv[N];intmain(void){
cin >> n >> P;
inv[1]=1;for(int i=2;i<=n;++i)
inv[i]=1LL*(P - P / i)* inv[P % i]% P;for(int i=1;i<=n;++i)printf("%d\n", inv[i]);return0;}