倍增求LCA

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,root;
int fa[500005][22],lg[500005],dep[500005];
int to[1000005],nxt[1000005],head[500005],tot;
inline int read(){
	char ch=getchar();
	int x=0,f=1;
	while((ch<'0' || ch>'9') && ch!='-'){
		ch=getchar();
	}
	if(ch=='-'){
		f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<3)+(x<<1)+ch-'0';
		ch=getchar();
	}
	return x*f;
}
void dfs(int x,int y){
	dep[x]=dep[y]+1;
	fa[x][0]=y;
	for(int i=1;1<<i<=dep[x];i++){
		fa[x][i]=fa[fa[x][i-1]][i-1];
	}
	for(int i=head[x];i;i=nxt[i]){
		if(to[i]!=y){
			dfs(to[i],x);
		}
	}
}
void add_edge(int x,int y){
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
int LCA(int x,int y){
	if(dep[x]<dep[y]){
		swap(x,y);
	}
	while(dep[x]>dep[y]){
		x=fa[x][lg[dep[x]-dep[y]]-1];
	}
	if(x==y){
		return y;
	}
	for(int k=lg[dep[x]]-1;k>=0;k--){
		if(fa[x][k]!=fa[y][k]){
			x=fa[x][k];
			y=fa[y][k];
		}
	}
	return fa[x][0];
}
int main(){
	int x,y;
	n=read();
	m=read();
	root=read();
	for(int i=1;i<n;i++){
		x=read();
		y=read();
		add_edge(x,y);
		add_edge(y,x);
	}
	for(int i=1;i<=n;i++){
		lg[i]=lg[i-1]+(1<<lg[i-1]==i);
	}
	dfs(root,0);
	while(m--){
		x=read();
		y=read();
		cout<<LCA(x,y)<<endl;
	}
	return 0;
}

并查集

#include<iostream>
using namespace std;
const int N=20005;
int pa[N];
int find_(int x){
	if(pa[x]!=x){
		pa[x]=find_(pa[x]);
	}
	return pa[x];
}
void union_(int x,int y){
	pa[find_(y)]=find_(x);
}
bool judge(int x,int y){
	return find_(x)==find_(y);
}
int main(){
	int n,m,q,a,b,c,d;
	cin>>n>>m;
	for(int i=0;i<=N;i++){
		pa[i]=i;
	}
	for(int i=0;i<m;i++){
		cin>>a>>b;
		if(!judge(a,b)){
			union_(a,b);
		}
	}
	cin>>q;
	for(int i=0;i<q;i++){
		cin>>c>>d;
		cout<<(judge(c,d)?"Yes":"No")<<endl;
	}
}

单调队列

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int n,k,a[N];
int main(){
	deque<int>qmin,pmin;
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	qmin.push_back(a[1]);
	pmin.push_back(1);
	if(k==1){
		cout<<a[1]<<" ";
	}
	for(int tl=2;tl<=n;tl++){
		if(!pmin.empty() && pmin.front()<=tl-k){
			qmin.pop_front();
			pmin.pop_front();
		}
		while(!qmin.empty() && qmin.back()>=a[tl]){
			qmin.pop_back();
			pmin.pop_back();
		}
		qmin.push_back(a[tl]);
		pmin.push_back(tl);
		if(tl>=k){
			cout<<qmin.front()<<" ";
		}
	}
	cout<<endl;
}

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a,heap[N],n,len=0;
void puthp(int hp[],int &l,int x){
	int index=++l;
	hp[index]=x;
	while(index!=1 && hp[index]<hp[index>>1]){
		swap(hp[index],hp[index>>1]);
		index>>=1;
	}
}
int gethp(int hp[],int &l){
	int ret=hp[1],pa=1,son;
	hp[1]=hp[l];
	hp[l--]=0;
	while(pa<<1<=l){
		son=pa<<1;
		if(son<l && hp[son|1]<hp[son]){
			son++;
		}
		if(hp[pa]<hp[son]){
			break;
		}
		swap(hp[son],hp[pa]);
		pa=son;
	}
	return ret;
}
int main(){
	cin>>n;
	int op,x;
	while(n--){
		cin>>op;
		if(op==1){
			cin>>x;
			puthp(heap,len,x);
		}
		else if(op==2){
			cout<<heap[1]<<endl;
		}
		else if(op==3){
			gethp(heap,len);
		}
	}
	return 0;
}

多重背包二进制拆分

#include<bits/stdc++.h>
using namespace std;
const int N=105,W=50005;
int n,v,w[N],c[N],x[N],f[W],ans;
main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	scanf("%d%d",&n,&v);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&w[i],&c[i],&x[i]);
	}
	for(int i=1;i<=n;i++){
		if(x[i]*w[i]>=v){
			for(int j=w[i];j<=v;j++){
				f[j]=max(f[j],f[j-w[i]]+c[i]);
				ans=max(ans,f[j]);
			}
		}
		else{
			for(int k=1;x[i]>0;k<<=1){
				int r=min(k,x[i]);
				for(int j=v;j>=w[i]*r;j--){
					f[j]=max(f[j],f[j-w[i]*r]+c[i]*r);
					ans=max(ans,f[j]);
				}
				x[i]-=r;
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

高精度乘法

#include<iostream>
#include<cstring>
using namespace std;
int main(){
	int a[2000]={},b[2000]={},c[40000]={},i,j,x=0,lena,lenb,lenc;
	char a1[2000],b1[2000];
	cin>>a1>>b1;
	lena=strlen(a1);
	lenb=strlen(b1);
	lenc=lena+lenb;
	for(i=0;i<lena;i++){
		a[lena-i]=a1[i]-48;
	}
	for(i=0;i<lenb;i++){
		b[lenb-i]=b1[i]-48;
	}
	for(i=1;i<=lena;i++){
		for(j=1;j<=lenb;j++){
			c[i+j-1]+=a[i]*b[j]+x;
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		c[i+lenb]=x;
		x=0;
	}
	while(!c[lenc]&&lenc>1){
		lenc--;
	}
	for(i=lenc;i>=1;i--){
		cout<<c[i];
	}
	cout<<endl;
	return 0;
}

快速幂

#include<iostream>
using namespace std;
long long a,b,p;
long long quick_power(long long x,long long y){
	long long ans=1,base=x;
	while(y>0){
		if(y&1){
			ans*=base;
			ans%=p;
		}
		base*=base;
		base%=p;
		y>>=1;
	}
	return ans;
}
int main(){
	cin>>a>>b>>p;
	long long s=quick_power(a,b);
	cout<<a<<"^"<<b<<" mod "<<p<<"="<<s<<endl;
	return 0;
}

链式前向星

#include<iostream>
#include<cstring>
using namespace std;
struct Node{
	int to,w,nxt;
	Node(){
		to=0;
		w=0;
		nxt=-1;
	}
};
Node edge[100000];
int n,m,ecnt=0,head[100000];
void add_edge(int from,int to,int value){
	ecnt++;
	edge[ecnt].to=to;
	edge[ecnt].w=value;
	edge[ecnt].nxt=head[from];
	head[from]=ecnt;
}
void add_double_edge(int a,int b,int value){
	add_edge(a,b,value);
	add_edge(b,a,value);
}
int main(){
	int x,y,v;
	memset(head,-1,sizeof(head));
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>v;
		add_double_edge(x,y,v);		
		//add_edge(x,y,v);			 
	}
	for(int i=1;i<=n;i++){
		cout<<"Node "<<i<<": ";
		for(int j=head[i];j>=0;j=edge[j].nxt){
			cout<<"[to: "<<edge[j].to<<", value:"<<edge[j].w<<"] ";
		}
		cout<<endl;
	}
	return 0;
}

平衡树Splay

#include<bits/stdc++.h>
using namespace std;
const int N=100005,INF=1e9;
int n;
struct Node{
	int s[2]; 
	int p; 
	int v; 
	int cnt; 
	int siz; 
	void init(int p1,int v1){
		p=p1, v=v1;
		cnt=siz=1;
	}
};
struct Splay_tree{
	Node tr[N];
	int root;
	int idx; 
	int ls(int x){
		return tr[x].s[0];
	}
	int rs(int x){
		return tr[x].s[1];
	}
	void pushup(int x){
		tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+tr[x].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){
				(ls(y)==x)^(ls(z)==y)?rotate(x):rotate(y);
			}
		rotate(x);
		}
		if(k==0){
			root=x;
		}
	}
	void insert(int v){
		int x=root,p=0;
		while(x && tr[x].v!=v){
			p=x;
			x=tr[x].s[v>tr[x].v];
		}
		if(x){
			tr[x].cnt++;
		}
		else{
			x=++idx;
			tr[p].s[v>tr[p].v]=x;
			tr[x].init(p,v);
		}
		splay(x,0);
	}
	void find(int v){
		int x=root;
		while(tr[x].s[v>tr[x].v]&&v!=tr[x].v){
			x=tr[x].s[v>tr[x].v];
		}
		splay(x,0);
	}
	int getpre(int v){
		find(v);
		int x=root;
		if(tr[x].v<v){
			return x;
		}
		x=ls(x);
		while(rs(x)){
			x=rs(x);
		}
		return x;
	}
	int getnxt(int v){ 
		find(v);
		int x=root;
		if(tr[x].v>v){
			return x;
		}
		x=rs(x);
		while(ls(x)){
			x=ls(x);
		}
		return x;
	}
	void del(int v){ 
		int pre=getpre(v);
		int suc=getnxt(v);
		splay(pre,0);
		splay(suc,pre);
		int del=tr[suc].s[0];
		if(tr[del].cnt>1){
			tr[del].cnt--, splay(del,0);
		}
		else{
			tr[suc].s[0]=0,splay(suc,0);
		}
	}
	int getrank(int v){ 
		find(v);
		return tr[tr[root].s[0]].siz;
	}
	int getval(int k){ 
		int x=root;
		while(1){
			int y=ls(x);
			if(tr[y].siz+tr[x].cnt<k){
				k-=tr[y].siz+tr[x].cnt;
				x=rs(x);
			}
			else if(tr[y].siz>=k){
				x=y;
			}
			else{
				break;
			}
		}
		splay(x,0);
		return tr[x].v;
	}
};
Splay_tree s;
int main(){
	s.insert(-INF);
	s.insert(INF);
	scanf("%d",&n);
	while(n--){
		int op,x;
		scanf("%d%d",&op,&x);
		if(op==1) s.insert(x);
		if(op==2) s.del(x);
		if(op==3) printf("%d\n",s.getrank(x));
		if(op==4) printf("%d\n",s.getval(x+1));
		if(op==5) printf("%d\n",s.tr[s.getpre(x)].v);
		if(op==6) printf("%d\n",s.tr[s.getnxt(x)].v);
	}
	return 0;
}

扫描线

#include<bits/stdc++.h>
#define N 1000006
using namespace std;
struct Point{
	int v,num,tag;
};
struct Event{
	int x1,x2,v;
};
struct Rect{
	int x1,y1,x2,y2;
};
long long n,x[N],y[N],xcnt,ycnt,ans;
Point tr[4*N];
vector<Event> ev[N];
Rect g[N];
void pushup(int x){
	if(tr[x<<1].v == tr[x<<1|1].v){
		tr[x].v=tr[x<<1].v;
		tr[x].num=tr[x<<1].num+tr[x<<1|1].num;
	}
	else{
		int p=(tr[x<<1].v<tr[x<<1|1].v)?(x<<1):(x<<1|1);
		tr[x].v=tr[p].v;
		tr[x].num=tr[p].num;
	}
}
void pushdown(int l,int r,int x){
	int mid=(l+r)>>1;
	if(tr[x].tag!=0){
		tr[x<<1].tag+=tr[x].tag;
		tr[x<<1|1].tag+=tr[x].tag;
		tr[x<<1].v+=tr[x].tag;
		tr[x<<1|1].v+=tr[x].tag;
		tr[x].tag=0;
	}
}
void build(int l,int r,int x_){
	if(l==r){
		tr[x_].num=x[l]-x[l-1];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,x_<<1);
	build(mid+1,r,x_<<1|1);
	pushup(x_);
}
void change(int l,int r,int x,int cl,int cr,int va){
	if(cl<=l && r<=cr){
		tr[x].v+=va;
		tr[x].tag+=va;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(l,r,x);
	if(cl<=mid){
		change(l,mid,x<<1,cl,cr,va);
	}
	if(cr>mid){
		change(mid+1,r,x<<1|1,cl,cr,va);
	}
	pushup(x);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>g[i].x1>>g[i].y1>>g[i].x2>>g[i].y2;
		x[++xcnt]=g[i].x1;
		x[++xcnt]=g[i].x2;
		y[++ycnt]=g[i].y1;
		y[++ycnt]=g[i].y2;
	}
	sort(x+1,x+xcnt+1);
	sort(y+1,y+ycnt+1);
	xcnt=unique(x+1,x+xcnt+1)-x-1;
	ycnt=unique(y+1,y+ycnt+1)-y-1;
	for(int i=1;i<=n;i++){
		int x1,y1,x2,y2;
		x1=lower_bound(x+1,x+xcnt+1,g[i].x1)-x;
		y1=lower_bound(y+1,y+ycnt+1,g[i].y1)-y;
		x2=lower_bound(x+1,x+xcnt+1,g[i].x2)-x;
		y2=lower_bound(y+1,y+ycnt+1,g[i].y2)-y;
		ev[y1].push_back((Event){x1+1,x2,1});
		ev[y2].push_back((Event){x1+1,x2,-1});
	}
	x[0]=x[1]; y[0]=y[1];
	build(1,xcnt,1);
	for(int i=1;i<=ycnt;i++){
		int t=tr[1].num;
		if(tr[1].v>0){
			t=0;
		}
		ans+=(y[i]-y[i-1])*(x[xcnt]-x[1]-t);
		for(int j=0;j<(int)(ev[i].size());j++){
			change(1,xcnt,1,ev[i][j].x1,ev[i][j].x2,ev[i][j].v);
		}
	}
	cout<<ans<<endl;
	return 0;
}

线段树

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
struct Point{
	int v,tag;
};
struct Tree{
	Point tr[4*N];
	void pushup(int x){
		tr[x].v=tr[x<<1].v+tr[x<<1|1].v;
	}
	void pushdown(int l,int r,int x){
		int mid=(l+r)>>1;
		if(tr[x].tag!=0){
			tr[x<<1].tag+=tr[x].tag;
			tr[x<<1|1].tag+=tr[x].tag;
			tr[x<<1].v+=(mid+1-l)*tr[x].tag;
			tr[x<<1|1].v+=(r-mid)*tr[x].tag;
			tr[x].tag=0;
		}
	}
	void build(int l,int r,int x){
		if(l==r){
			tr[x].v=a[l];
			return;
		}
		int mid=(l+r)>>1;
		build(l,mid,x<<1);
		build(mid+1,r,x<<1|1);
		pushup(x);
	}
	int query(int l,int r,int x,int ql,int qr){
		if(ql<=l && r<=qr){
			return tr[x].v;
		}
		int mid=(l+r)>>1;
		int ans=0;
		pushdown(l,r,x);
		if(ql<=mid){
			ans+=query(l,mid,x<<1,ql,qr);
		}
		if(qr>mid){
			ans+=query(mid+1,r,x<<1|1,ql,qr);
		}
		return ans;
	}
	void change(int l,int r,int x,int cl,int cr,int va){
		if(cl<=l && r<=cr){
			tr[x].v+=(r-l+1)*va;
			tr[x].tag+=va;
			return;
		}
		int mid=(l+r)>>1;
		pushdown(l,r,x);
		if(cl<=mid){
			change(l,mid,x<<1,cl,cr,va);
		}
		if(cr>mid){
			change(mid+1,r,x<<1|1,cl,cr,va);
		}
		pushup(x);
	}
};
int main(){
	int op,l,r,x;
	cin>>n>>q;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,n,1);
	for(;q--;){
		cin>>op;
		switch(op){
			case 1:
				cin>>l>>r>>x;
				change(1,n,1,l,r,x);
				break;
			case 2:
				cin>>l>>r;
				cout<<query(1,n,1,l,r)<<endl;
				break;
		}
	}
	return 0;
}

线性筛

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,cnt,prim[N];
bool vis[N];
int main(){
	cin>>n;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prim[++cnt]=i;
		}
		for(int j=1;j<=cnt && i*prim[j]<=n;j++){
			int m=i*prim[j];
			vis[m]=1;
			if(i%prim[j]==0){
				break;
			}
		}
	}
	cout<<cnt<<endl;
	for(int i=1;i<=cnt;i++){
		cout<<prim[i]<<" ";
	}
	cout<<endl;
	return 0;
}

线性筛求约数个数

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,cnt,prim[N],prims[N],snum[N]={0,1};
bool vis[N];
int main(){
	cin>>n;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prim[++cnt]=i;
			prims[i]=1;
			snum[i]=2;
		}
		for(int j=1;j<=cnt && i*prim[j]<=n;j++){
			int m=i*prim[j];
			vis[m]=1;
			if(i%prim[j]==0){
				prims[m]=prims[i]+1;
				snum[m]=snum[i]/(prims[i]+1)*(prims[i]+2);
				break;
			}
			snum[m]=snum[i]*snum[prim[j]];
			prims[m]=1;
		}
	}
	for(int i=1;i<=n;i++){
		cout<<snum[i]<<" ";
	}
	cout<<endl;
	return 0;
}

匈牙利算法

#include<bits/stdc++.h>
using namespace std;
const int N=502;
int n,m,e,ans;
int tim[N],mch[N];
vector<int>G[N];
bool dfs(int u,int t){
	if(tim[u]==t){
		return false;
	}
	tim[u]=t;
	for(auto v:G[u]){
		if(!mch[v] || dfs(mch[v],t)){
			mch[v]=u;
			return true;
		}
	}
	return false;
}
int main(){
	int u,v;
	cin>>n>>m>>e;
	while(e--){
		cin>>u>>v;
		G[u].push_back(v);
	}
	for(int i=1;i<=n;i++){
		if(dfs(i,i)){
			ans++;
		}
	}
	cout<<ans<<endl; 
	return 0;
}

一笔画

#include<iostream>
using namespace std;
int n,m,deg[1001]={},ans[1001]={};
bool go[1001][1001]={};
void print(int k){
	for(int i=0;i<=k;i++){
		cout<<ans[i]<<" ";
	}
	cout<<endl;
}
void dfs(int k,int x){
	for(int i=1;i<=n;i++){
		if(i!=x && go[x][i] && deg[i]){
			deg[i]--;
			ans[++k]=i;
			go[x][i]=go[i][x]=0; 
			if(k==m){
				print(k);
			}
			else{
				dfs(k,i);
			}
			go[x][i]=go[i][x]=1;
			ans[k--]=0;
			deg[i]++;
		}
	}
}
int main(){
	int x,y,s=0,index;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>x>>y;
		go[x][y]=go[y][x]=1;
		deg[x]++; deg[y]++;
	}
	for(int i=1;i<=n;i++){
		if(deg[i]%2){
			if(s<2){
				s++;
				index=i;
			}
			else{
				cout<<"Impossible!"<<endl;
				return 0;
			}
		}
	}
	ans[0]=s?index:1;
	dfs(0,ans[0]);
}

字典树

#include<bits/stdc++.h>
using namespace std;
const int N=3000006;
int n,q,t[N][65],cnt[N],idx;
char s[N];
int ord(char x){
	if(x>='0' && x<='9'){
		return x-'0';
	}
	else if(x>='A' && x<='Z'){
		return x-'A'+10;
	}
	else{
		return x-'a'+36;
	}
}
void insert(char s[]){
	int l=strlen(s),p=0;
	for(int i=0;i<l;i++){
		int c=ord(s[i]);
		if(!t[p][c]){
			t[p][c]=++idx;
		}
		cnt[t[p][c]]++;
		p=t[p][c];
	}
}
int search(char s[]){
	int l=strlen(s),p=0;
	for(int i=0;i<l;i++){
		int c=ord(s[i]);
		if(!t[p][c]){
			return 0;
		}
		p=t[p][c];
	}
	return cnt[p];
}
int main(){
	cin>>n>>q;
	while(n--){
		cin>>s;
		insert(s);
	}
	while(q--){
		cin>>s;
		cout<<search(s)<<endl;
	}
	return 0;
}

DIJ

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
struct Edge{
	int to,val;
};
int n,m,x,y,a,s,t,u,minn,dis[N]={},pre[N];
bool visit[N];
vector<Edge>G[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a;
		G[x].push_back((Edge){y,a});
		G[y].push_back((Edge){x,a});
	}
	cin>>s>>t;
	for(int i=1;i<=n;i++){
		dis[i]=((i==s)?0:0x3fffffff);
	}
	for(int i=1;i<=n;i++){
		minn=0x3fffffff;
		for(int j=1;j<=n;j++){
			if(!visit[j]){
				u=j;
				break;
			}
		}
		for(int j=1;j<=n;j++){
			if(!visit[j] && dis[j]<minn){
				minn=dis[j];
				u=j;
			}
		}
		visit[u]=1;
		for(auto v:G[u]){
			if(!visit[v.to] && dis[u]+v.val<dis[v.to]){
				dis[v.to]=dis[u]+v.val;
//				pre[v.to]=u;				
			} 
		}
	}
	cout<<dis[t]<<endl;
	return 0;
}

DIJ(堆优化)

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
struct Edge{
	int to,val;
};
int n,m,x,y,a,s,t,u,minn,dis[N]={},pre[N];
bool visit[N];
vector<Edge>G[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a;
		G[x].push_back((Edge){y,a});
		G[y].push_back((Edge){x,a});
	}
	cin>>s>>t;
	for(int i=1;i<=n;i++){
		dis[i]=((i==s)?0:0x3fffffff);
	}
	for(int i=1;i<=n;i++){
		minn=0x3fffffff;
		for(int j=1;j<=n;j++){
			if(!visit[j]){
				u=j;
				break;
			}
		}
		for(int j=1;j<=n;j++){
			if(!visit[j] && dis[j]<minn){
				minn=dis[j];
				u=j;
			}
		}
		visit[u]=1;
		for(auto v:G[u]){
			if(!visit[v.to] && dis[u]+v.val<dis[v.to]){
				dis[v.to]=dis[u]+v.val;
//				pre[v.to]=u;				
			} 
		}
	}
	cout<<dis[t]<<endl;
	return 0;
}

Floyed

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,x,y,a,s,t,w[N][N],dis[N][N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a;
		w[x][y]=w[y][x]=a;
	}
	cin>>s>>t;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dis[i][j]=w[i][j]?w[i][j]:0x3ffffff;
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(dis[i][j]>dis[i][k]+dis[k][j]){
					dis[i][j]=dis[i][k]+dis[k][j];
				}
			}
		}
	}
	cout<<dis[s][t]<<endl;
	return 0;
}

Kruskal

#include<bits/stdc++.h>
using namespace std;
const int N=10005;
struct Edge{
	int x,y,v;
}a[N];
int n,m,k,xx,yy,zz,mst,pa[N];
int find_(int x){
	if(pa[x]!=x){
		pa[x]=find_(pa[x]);
	}
	return pa[x];
}
void union_(int x,int y){
	pa[find_(y)]=find_(x);
}
bool cmp(Edge x,Edge y){
	return x.v<y.v;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>xx>>yy>>zz;
		a[i].x=xx;
		a[i].y=yy;
		a[i].v=zz;
	}
	for(int i=1;i<=n;i++){
		pa[i]=i;
	}
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++){
		if(find_(a[i].x)!=find_(a[i].y)){
			union_(a[i].x,a[i].y);
			mst+=a[i].v;
			k++;
		}
		if(k==n-1){
			break;
		}
	}
	cout<<mst<<endl;
	return 0;
}

Prim

#include<bits/stdc++.h>
using namespace std;
const int N=501;
struct Edge{
	int to,val;
};
int n,m,x,y,a,mst,u,min_dis[N];
vector<Edge>G[N];
bool visit[N];
int main(){
	cin>>n>>m;
	for(int i=0;i<=n;i++){
		min_dis[i]=0x3fffffff;
	}
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a;
		G[x].push_back((Edge){y,a});
		G[y].push_back((Edge){x,a});
	}
	min_dis[1]=0;
	for(int i=1;i<=n;i++){
		u=0;
		for(int j=1;j<=n;j++){
			if(!visit[j] && min_dis[j]<min_dis[u]){
				u=j;
			}
		}
		visit[u]=1;
		for(auto v:G[u]){
			if(!visit[v.to] && v.val<min_dis[v.to]){
				min_dis[v.to]=v.val;
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<min_dis[i]<<" ";
	}
	cout<<endl;
	for(int i=1;i<=n;i++){
		mst+=min_dis[i];
	}
	cout<<mst<<endl;
	return 0;
}

AC自动机

#include<bits/stdc++.h>
using namespace std;
const int N=501;
struct Edge{
	int to,val;
};
int n,m,x,y,a,mst,u,min_dis[N];
vector<Edge>G[N];
bool visit[N];
int main(){
	cin>>n>>m;
	for(int i=0;i<=n;i++){
		min_dis[i]=0x3fffffff;
	}
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a;
		G[x].push_back((Edge){y,a});
		G[y].push_back((Edge){x,a});
	}
	min_dis[1]=0;
	for(int i=1;i<=n;i++){
		u=0;
		for(int j=1;j<=n;j++){
			if(!visit[j] && min_dis[j]<min_dis[u]){
				u=j;
			}
		}
		visit[u]=1;
		for(auto v:G[u]){
			if(!visit[v.to] && v.val<min_dis[v.to]){
				min_dis[v.to]=v.val;
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<min_dis[i]<<" ";
	}
	cout<<endl;
	for(int i=1;i<=n;i++){
		mst+=min_dis[i];
	}
	cout<<mst<<endl;
	return 0;
}

Manacher

#include<bits/stdc++.h>
using namespace std;
const tin N=11000010; 
string s,b;
int len,r[2*N];
int main(){
	cin>>s;
	len=s.length();
	b+="#";
	for(int i=0;i<len;i++){
		b+=s[i];
		b+="#";
	}
	int pos=0;
	for(int i=0;i<2*len+1;i++){
		if(pos+r[pos]-1>i){
			r[i]=min(r[2*pos-i],pos+r[pos]-i);
		}
		else{
			r[i]=1;
		}
		while(i+r[i]<2*len+1 && i-r[i]>=0 && b[i+r[i]]==b[i-r[i]]){
			r[i]++;
		}
		if(i+r[i]>pos+r[pos]){
			pos=i;
		}
	}
	int ans=-1;
	for(int i=0;i<2*len+1;i++){
		ans=max(ans,r[i]-1);
	}
	cout<<ans<<endl;
	return 0;
}

Tarjan

#include <bits/stdc++.h>
using namespace std;
const int N=1000006;
int n,m,color[N],e[N],nxt[N],head[N],cnt,used[N],fa[N],ans,num,fa2[N];
int dfn[N],low[N],ti,s[N],top,exist[N];
void addEdge(int a,int b){
	cnt++;
	e[cnt]=b;
	nxt[cnt]=head[a];
	head[a]=cnt;
}
void tarjan(int u){
	dfn[u]=low[u]=++ti;
	s[++top]=u;
	exist[u]=1;
	for(int i=head[u];i;i=nxt[i]){
		int v=e[i];
		if(dfn[v]==0){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(exist[v]==1){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		num++;
		while(s[top+1]!=u){
			int x=s[top];
			exist[x]=0;
			fa[x]=u;
			fa2[x]=num;
			top--;
		}
	}
} 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		addEdge(x,y);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	for(int i=1;i<=num;i++){
		for(int j=1;j<=n;j++){
			if(fa2[j]==i){
				cout<<j<<" "; 
			}
		}
		cout<<endl;
	}
	return 0;
}

Tarjan求点双连通分量

#include <bits/stdc++.h>
using namespace std;
const int N=1000006;
int n,m,bnum;
int dfn[N],low[N],ti,tmp=-1;
vector<int>G[N],bcc[N];
stack<int>S;
void tarjan(int u,int fa){
	dfn[u]=low[u]=++ti;
	S.push(u);
	int cnt=0;
	for(auto v:G[u]){
		if(dfn[v]==0){
			cnt++;
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(dfn[u]<=low[v]){
				bnum++;
				while(tmp!=v){
					tmp=S.top();
					S.pop();
					bcc[bnum].push_back(tmp);
				}
				bcc[bnum].push_back(u);
			}
		}
		else{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(cnt==0 && fa==0){
		bcc[++bnum].push_back(u);
	}
} 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			while(!S.empty()){
				S.pop();
			}
			tarjan(i,0);
		}
	}
	cout<<bnum<<endl;
	for(int i=1;i<=bnum;i++){
		int bsize=bcc[i].size();
		cout<<bsize<<" ";
		for(int j=0;j<bsize;j++){
			cout<<bcc[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<endl;
	return 0;
}

Tarjan求割点

#include <bits/stdc++.h>
using namespace std;
const int N=1000006;
int n,m,r,ans;
int dfn[N],low[N],ti;
bool is_cut[N];
vector<int>G[N];
void tarjan(int u){
	dfn[u]=low[u]=++ti;
	int cnt=0;
	for(auto v:G[u]){
		if(dfn[v]==0){
			cnt++;
			tarjan(v);
			low[u]=min(low[u],low[v]);
			if((u!=r && dfn[u]<=low[v]) || (u==r && cnt>1)){
				is_cut[u]=1;
			}
		}
		else{
			low[u]=min(low[u],dfn[v]);
		}
	}
} 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			r=i;
			tarjan(i);
		}
	}
	for(int i=1;i<=n;i++){
		if(is_cut[i]){
			ans++;
		}
	}
	cout<<ans<<endl;
	for(int i=1;i<=n;i++){
		if(is_cut[i]){
			cout<<i<<" ";
		}
	}
	cout<<endl;
	return 0;
}

Tarjan求强连通分量

#include <bits/stdc++.h>
using namespace std;
const int N=1000006;
struct Edge{
	int u,v;
};
int n,m,a[N],dis[N],belong[N],ans;
int dfn[N],low[N],ti,in[N];
bool vis[N];
vector<int>G[N],G_[N];
vector<Edge>E; 
stack<int>s; 
void tarjan(int u){
	dfn[u]=low[u]=++ti;
	s.push(u);
	vis[u]=1;
	for(auto v:G[u]){
		if(dfn[v]==0){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		int v;
		do{
			v=s.top();
			s.pop();
			vis[v]=0;
			belong[v]=u;
			a[u]+=a[v];
		}while(u!=v);
		a[u]>>=1;
	}
} 
void bfs(){
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!in[i] && belong[i]==i){
			q.push(i);
			dis[i]=a[i];
			ans=max(ans,a[i]);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto v:G_[u]){
			in[v]--;
			dis[v]=max(dis[v],dis[u]+a[v]);
			ans=max(ans,dis[v]);
			if(!in[v]){
				q.push(v);
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		G[x].push_back(y);
		E.push_back(Edge{x,y});
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	for(auto e:E){
		int u=e.u,v=e.v;
		if(belong[u]!=belong[v]){
			G_[belong[u]].push_back(belong[v]);
			in[belong[v]]++;
		}
	}
	bfs();
	cout<<ans<<endl;
	return 0;
}

珂朵莉树 set

struct node
{
    ll l, r;
    mutable ll v;
    //mutable 的意思是“可变的”,意味着可以直接修改已经插入 set 中的元素的 v 值,
    //而不用将该元素取出后重新加入 set
    node(ll l, ll r, ll v) : l(l), r(r), v(v) {} // 构造函数
    bool operator<(const node& o) const { return l < o.l; } // 重载小于运算符
};

set<node> tree;
auto split(ll pos)
{
    auto it = tree.lower_bound(node(pos, 0, 0));
    //如果已经存在以pos为左端点的节点,直接返回
    if (it != tree.end() && it->l == pos) return it;
    //否则往前数一个节点,该节点为x所在的区间
    it--; 
    ll l = it->l, r = it->r, v = it->v;
    tree.erase(it); // 删除该节点
    tree.insert(node(l, pos - 1, v)); // 插入<l,pos-1,v>和<pos,r,v>
    return tree.insert(node(pos, r, v)).first; // 返回以pos开头的那个节点的迭代器
                                               // insert默认返回值是一个pair,第一个成员是我们要的
}


//区间赋值
void assign(ll l, ll r, ll v)
{
    //在进行求取区间左右端点操作时,必须先 split 右端点,再 split 左端点。
    //若先 split 左端点,返回的迭代器可能在 split 右端点的时候失效,可能会导致 RE。
    auto end = split(r + 1), begin = split(l);
    tree.erase(begin, end); // 清除一系列节点
    tree.insert(node(l, r, v)); // 插入新的节点
}

//区间加
void add(ll l, ll r, ll v)
{
    auto end = split(r + 1);
    for (auto it = split(l); it != end; it++)
        it->v += v;
}

珂朵莉树 set

struct Node
{
    int l,r;
    mutable int v;
    Node(const int &il, const int &ir, const int &iv) : l(il), r(ir), v(iv) {}//构造函数
    inline bool operator<(const Node &o) const { return l < o.l; }
};
set<Node> ct;//Chtholly Tree
typedef set<Node>::iterator it;
it split(int x) 
{
  if (x > n) return ct.end();
  it iter = --ct.upper_bound((Node){x, 0, 0});
  if (iter->l == x) return iter;
  int l = iter->l, r = iter->r, v = iter->v;
  ct.erase(iter);
  ct.insert(Node(l, x - 1, v));
  return ct.insert(Node(x, r, v)).first;
}
void assign(int l, int r, int v) 
{
  it itr = split(r + 1), itl = split(l);
  ct.erase(itl, itr);
  ct.insert(Node(l, r, v));
}
void performance(int l, int r) 
{
  it itr = split(r + 1), itl = split(l);
  for (; itl != itr; ++itl) 
  {
    // Puts your code here!
    //这个循环迭代 [split(l),split(r+1)] 中的每一个元素
  }
}
void add(int l, int r,int v) 
{
  it itr = split(r + 1), itl = split(l);
  for (; itl != itr; ++itl) 
  {
    itl->v += v;//由于我们的v声明时使用了mutable关键字,直接更改即可
  }
}
inline int kth(int l,int r,int k)
{
   vector< pair<int,int> > a;
   it itr=split(r+1),itl=split(l);
   for(it iter=itl;iter!=itr;iter++)
      a.push_back(pair<int,int>(iter->v,(iter->r)-(iter->l)+1));//使用pair的构造函数
   sort(a.begin(),a.end());
   for(vector< pair<int,int> >::iterator iter=a.begin();iter!=a.end();iter++)
   {
      k-=iter->second;
      if(k<=0)return iter->first;
   }
   return -1;
}
long long fpow(long long x,long long y,long long mod)
{
    long long ans=1;
    x%=mod;
    while(y) //快速幂
    {
        if(y&1)ans=ans*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ans;
}
int sum(int l,int r,int x,int y)
{
   int ans=0;
   it itr=split(r+1),itl=split(l);
   for(it it=itl;it!=itr;it++)
      ans=(ans+fpow(it->v,x,y)*((it->r)-(it->l)+1))%y;//注意使用fpow函数,这个函数是我们自己定义的快速幂。
   return ans;
}

珂朵莉树 map

struct ODT {
    const int n;
    map<int, int> mp;
    ODT(int n) : n(n) { mp[-1] = 0 }
    void split(int x) {
        auto it = prev(mp.upper_bound(x)); //找到左端点小于等于x的区间
        mp[x] = it->second; //设立新的区间,并将上一个区间储存的值复制给本区间。
    }
    void assign(int l, int r, int v) { // 注意,这里的r是区间右端点+1
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            it = mp.erase(it);
        }
        mp[l] = v;
    }
    void update(int l, int r, int c) { // 其他操作
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            // 根据题目需要做些什么
            it = next(it);
        }
    }
};

珂朵莉树 list

typedef long long int64;

struct Block {
    Block *next; // 链表下一节点
    int l, r; // 区间范围
    int64 val; // 区间上的值

    Block(Block *next, int l, int r, int64 val): next(next), l(l), r(r), val(val) {}
    bool operator<(const Block &b) const { return val < b.val; }
} *root;
// 返回左端点为 mid+1 的区间
Block *split(int mid) {
    for (Block *b = root; b; b = b->next) { // 遍历链表
        if (b->l == mid + 1) { // 左端点为 mid+1
            return b;
        }
        // 寻找能包含 mid 和 mid+1 的区间 [l, r],将其被拆分成 [l, mid] 和 [mid+1, r]
        if (b->l <= mid && mid + 1 <= b->r) {
            b->next = new Block(b->next, mid + 1, b->r, b->val);
            b->r = mid;
            return b->next;
        }
    }
    return nullptr; // 未找到,返回空
}
Block *lb, *rb;

// 预分裂,保证后续操作在 [l, r] 内部
void prepare(int l, int r) {
    lb = split(l - 1);
    rb = split(r);
}
void merge(int l, int r, int64 val) {
    prepare(l, r);
    lb->r = r; // 将区间 [lb.l, lb.r] 修改成 [lb.l, r]
    lb->val = val;
    lb->next = rb; // 将 [lb.l, r] 链至其右侧相邻区间
}
// 注:这里没有释放被删除节点的内存,若有需要可自行添加
// 区间更新
void add(int l, int r, int64 val) {
    prepare(l, r);
    for (Block *b = lb; b != rb; b = b->next)
        b->val += val;
}

// 区间第 k 小
int64 kth(int l, int r, int k) {
    prepare(l, r);
    vector<Block> blocks;
    for (Block *b = lb; b != rb; b = b->next)
        blocks.emplace_back(*b);
    sort(blocks.begin(), blocks.end());
    k--;
    for (Block b: blocks) {
        int cnt = b.r - b.l + 1;
        if (k >= cnt) k -= cnt;
        else return b.val;
    }
}

// 快速幂
int64 quick_pow(int64 x, int n, int64 mod) {
    x %= mod;
    int64 res = 1 % mod;
    for (; n; n >>= 1) {
        if (n & 1) res = res * x % mod;
        x = x * x % mod;
    }
    return res;
}

// 区间幂和
int64 pow_sum(int l, int r, int n, int64 mod) {
    prepare(l, r);
    int64 sum = 0;
    for (Block *b = lb; b != rb; b = b->next)
        sum += int64(b->r - b->l + 1) * quick_pow(b->val, n, mod);
    return sum % mod;
}

二分图匹配

#include<bits/stdc++.h>
#define int long long
using namespace std;
int mx[20005],my[20005],dx[20005],dy[20005],vis[20005],x,y,n,m,s;
vector<int> g[20005];
template <typename T> void read(T &t) {
	t=0; char ch=getchar(); int f=1;
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}

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

bool bfs(){
	queue<int> q;
	bool f=0;
	memset(dx,0,sizeof dx);
	memset(dy,0,sizeof dy);
	for(int i=1;i<=n;i++) if(!mx[i]) q.push(i);
	while(q.size()){
		int u=q.front();
		q.pop();
		for(auto v:g[u]){
			if(!dy[v]){
				dy[v]=dx[u]+1;
				if(!my[v]) f=1;
				else dx[my[v]]=dy[v]+1,q.push(my[v]);
			}
		}
	}
	return f;
}

bool dfs(int u){
	for(auto v:g[u]){
		if(!vis[v] && dy[v]==dx[u]+1){
			vis[v]=1;
			if(my[v]==0 || dfs(my[v])){
				mx[u]=v;
				my[v]=u;
				return 1;
			}
		}
	}
	return 0;
}

signed main(){
	read(n);
	read(m);
	read(s);
	for(int i=1;i<=s;i++){
		read(x),read(y);
		g[x].push_back(y);
	}
	int ans=0;
	while(bfs()){
		memset(vis,0,sizeof vis);
		for(int i=1;i<=n;i++){
			if(!mx[i] && dfs(i)) ans++;
		}
	}
	write(ans);
}