倍增求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);
}