c++复习板子
$${\color{red}construction}$$
\(\Large{数论}\)
点击查看
GCD
点击查看
-
B4025 最大公约数
gcd:
#include<bits/stdc++.h> #define int long long using namespace std; int a,b; inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; else ch=getchar(); } while(ch>='0'&&ch<='9'){ x=(x*10+ch-48); ch=getchar(); } return x*f; } int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } signed main(){ a=read(),b=read(); cout<<gcd(a,b); }
-
P2613 【模板】有理数取余
exgcd:
#include<bits/stdc++.h> #define int long long using namespace std; const int mod=19260817; int a,b; int pow(int a,int b){ int res=1; while(b){ if(b&1){ res=res*a%mod; } a=a*a%mod; b>>=1; } return res; } inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; else ch=getchar(); } while(ch>='0'&&ch<='9'){ x=(x*10+ch-48)%mod; ch=getchar(); } return x*f%mod; } signed main(){ a=read(),b=read(); if(!b){ cout<<"Angry!"; return 0; } cout<<a*pow(b,mod-2)%mod; }
-
质因数分解
#include<bits/stdc++.h> using namespace std; signed main(){ int n; cin>>n; for(int i=2;i<=n;i++){ if(n%i==0){ while(n%i==0){ cout<<i<<" "; n/=i; } } } if(n!=1){ cout<<n<<endl; } }
筛法
点击查看
-
P3383 【模板】线性筛素数
欧拉筛:
#include<bits/stdc++.h> #define int long long using namespace std; int n,q,tot; int prime[7000003]; //判断质数 bool vis[100000004]; void Prime_shai(int up){ memset(vis,1,sizeof vis); vis[1]=0; for(int i=2;i<=n;i++){ if(vis[i]){ prime[++tot]=i; //没有被筛就是质数 } for(int j=1;prime[j]*i<=n&&j<=tot;j++){ vis[i*prime[j]]=0; //被筛到打个标记 if(!i%prime[j]) break; //如果prime[j]是i的因子,那么以后得最小质因数就不在是prime[x]而是prime[j] } } } int a; signed main(){ cin>>n>>q; Prime_shai(n); while(q--){ cin>>a; cout<<prime[a]<<"\n"; } }
拉格朗日插值
点击查看
-
P4781 【模板】拉格朗日插值
//By yueyan_WZF #include <bits/stdc++.h> #define int long long using namespace std; inline int rd(){ int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9'){ if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } const int N=2e3+20; const int mod=998244353; int n,k; int x[N],y[N]; int power(int a,int b){ int res=1; while(b){ if(b&1) res=res*a%mod; a=a*a%mod;b>>=1; } return res; } int F(int xx){ int ans=0; for(int i=1;i<=n;i++){ int s1=1,s2=1; for(int j=1;j<=n;j++){ if(j==i) continue; s1=s1*(xx-x[j])%mod; s2=s2*(x[i]-x[j])%mod; } ans=(ans+((s1*power(s2,mod-2))%mod*y[i]%mod))%mod; } return (ans%mod+mod)%mod; } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); cin>>n>>k; for(int i=1;i<=n;i++) cin>>x[i]>>y[i]; cout<<F(k); return 0; }
莫比乌斯反演
点击查看
-
P2257 YY的GCD
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e7+15; int sum[N+5]; int mu[N+5]; int f[N+5]; bool vis[N+5]; int prime[N+5]; int cnt,n,m; void init(){ mu[1]=1; for(int i=2;i<=N;i++){ if(!vis[i]) { prime[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&prime[j]*i<=N;j++){ vis[i*prime[j]]=1; if(!(i%prime[j])) break; mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=cnt;i++){ for(int j=1;j*prime[i]<=N;j++){ f[j*prime[i]]+=mu[j]; } } for(int i=1;i<=N;i++) sum[i]=sum[i-1]+f[i]; } int T; void solve(int a,int b){ int l,r=0,ans=0; if(a>b) swap(a,b); for(l=1;l<=a;l=r+1){ r=min(a/(a/l),b/(b/l)); ans=ans+((a/l)*(b/l)*(sum[r]-sum[l-1])); } cout<<ans<<" \n"; } signed main(){ init(); cin>>T; while(T--){ cin>>n>>m; solve(n,m); } }
逆元
点击查看
-
P3811 【模板】模意义下的乘法逆元
#include<bits/stdc++.h> using namespace std; typedef long long ll; int ni[3000289]; int main(){ ll n,p; scanf("%lld%lld",&n,&p); ni[1]=1; cout<<"1"<<endl; for(int i=2;i<=n;++i){ ni[i]=1ll*(p-p/i)*ni[p%i]%p; printf("%d\n",ni[i]); } }
高斯消元
点击查看
-
P3389 【模板】高斯消元法
#include<bits/stdc++.h> using namespace std; double k[102][102]; double ans[103]; double Min=1e-7; int n; signed main(){ cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n+1;j++) cin>>k[i][j]; } for(int i=1;i<=n;i++){ int id=i; for(int j=i+1;j<=n;j++){ if(abs(k[j][i])>abs(k[id][i])) id=j; } //cout<<i<<" "<<id<<" "<<k[id][i]<<endl; if(abs(k[id][i])<Min){ // cout<<i<<" "<<id<<" "<<k[id][i]<<endl; cout<<"No Solution\n"; return 0; } swap(k[id],k[i]); double t=k[i][i]; for(int j=i+1;j<=n+1;j++) k[i][j]/=k[i][i]; for(int j=i+1;j<=n;j++){ t=k[j][i]; for(int p=i;p<=n+1;p++){ k[j][p]-=k[i][p]*t; } } } ans[n]=k[n][n+1]; for(int i=n-1;i>=1;i--){ ans[i]=k[i][n+1]; for(int j=i+1;j<=n;j++){ ans[i]-=(k[i][j]*ans[j]); } } for(int i=1;i<=n;i++){ printf("%.2lf\n",ans[i]); } }
整除分块
点击查看
-
P2261 [CQOI2007] 余数求和
//By yueyan_WZF #include <bits/stdc++.h> #define int long long using namespace std; inline int rd(){ int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9'){ if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } int n,k; signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); cin>>n>>k; int r; int ans=n*k; for(int l=1;l<=n;l=r+1){ if(k/l!=0) r=min(k/(k/l),n); else r=n; ans-=(k/l)*(r-l+1)*(l+r)/2; } cout<<ans; return 0; }
\(\Large{图论}\)
点击查看
最短路
点击查看
-
P3371 【模板】单源最短路径(弱化版)
SPFA :
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,u,v,w,s; struct node{ int to,nxt,w; }z[10000040]; //链式前向星 int cnt; int h[1000004]; int dis[1000004]; int vis[1000004]; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].nxt=h[x]; z[cnt].w=w; h[x]=cnt; } void SPFA(int start){ for(int i=1;i<=n;i++) dis[i]=1e11,vis[i]=0; vis[start]=1; queue<int> p; dis[start]=0; p.push(start); while(!p.empty()){ int x=p.front(); p.pop(); vis[x]=0; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+z[i].w){ dis[y]=z[i].w+dis[x]; if(!vis[y]){ vis[y]=1; p.push(y); } } } } } signed main(){ cin>>n>>m>>s; for(int i=1;i<=m;i++){ scanf("%lld%lld%lld",&u,&v,&w); add(u,v,w); } SPFA(s); for(int i=1;i<=n;i++){ if(dis[i]!=1e11) cout<<dis[i]<<" "; else cout<<"2147483647 "; } }
-
P4779 【模板】单源最短路径(标准版)
迪杰斯特拉:
#include<bits/stdc++.h> #define int long long using namespace std; typedef pair<int,int> pii; int n,m,u,v,w,s; struct node{ int to,nxt,w; }z[10000040]; //链式前向星 int cnt; int h[1000004]; int dis[1000004]; int vis[1000004]; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].nxt=h[x]; z[cnt].w=w; h[x]=cnt; } void dijie(int start){ for(int i=1;i<=n;i++) dis[i]=1e11,vis[i]=0; dis[start]=1; priority_queue<pii,vector<pii>,greater<pii> > p; p.push(make_pair(0,start)); while(!p.empty()){ int x=p.top().second; p.pop(); if(vis[x]) continue; else{ vis[x]=1; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+z[i].w){ dis[y]=dis[x]+z[i].w; p.push(make_pair(dis[y],y)); } } } } } signed main(){ cin>>n>>m>>s; for(int i=1;i<=m;i++){ scanf("%lld%lld%lld",&u,&v,&w); add(u,v,w); } dijie(s); for(int i=1;i<=n;i++){ cout<<dis[i]<<" "; } }
-
B3647 【模板】Floyd
Floyd:
#include<bits/stdc++.h> using namespace std; int main(){ int n,m; cin>>n>>m; int a[102][102]; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ a[i][j]=0x3f3f3f3f; a[j][i]=0x3f3f3f3f; } } for(int i=1;i<=m;i++){ int a1,b,c; cin>>a1>>b>>c; if(a[a1][b]>c){ a[a1][b]=c; a[b][a1]=c; } } for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(a[i][k]+a[k][j]<a[i][j]){ a[i][j]=a[i][k]+a[k][j]; a[j][i]=a[i][k]+a[k][j]; } if(i==j){ a[i][j]=a[j][i]=0; } } } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cout<<a[i][j]<<" "; } cout<<endl; } }
-
P1144 最短路计数
#include<bits/stdc++.h> #define int long long using namespace std; const int Mod=100003; typedef pair<int,int> pii; int cnt,n,m,x,y; map<int,int> mp[2000040]; int h[3000004]; struct node{ int to,nxt; }z[4000004]; void add(int x,int y){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; } int ans[3000003]; int dis[3000004]; int vis[3000004]; void dijie(int start){ priority_queue<pii,vector<pii>,greater<pii> > p; for(int i=1;i<=n;i++) dis[i]=1e11,vis[i]=0; dis[start]=0; ans[start]=1; p.push({0,start}); while(!p.empty()){ int x=p.top().second; p.pop(); if(vis[x]) continue; else{ vis[x]=1; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+1){ dis[y]=dis[x]+1; ans[y]=ans[x]; p.push({dis[y],y}); } else if(dis[y]==dis[x]+1){ ans[y]+=ans[x]; ans[y]%=Mod; } } } } } signed main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>x>>y; if(x==y) continue; else{ // if(mp[x].count(y)) continue; //判重边 add(x,y); add(y,x); mp[x][y]=1; mp[y][x]=1; } } dijie(1); for(int i=1;i<=n;i++){ cout<<ans[i]<<"\n"; } }
-
P5960 【模板】差分约束
#include<bits/stdc++.h> #define int long long using namespace std; int n,m; struct node{ int to,nxt,w; }z[1000004]; int cnt; int h[1000004]; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].w=w; z[cnt].nxt=h[x]; h[x]=cnt; } int dis[1000004]; int vis[1000004]; int tot[1000004]; bool SPFA(int s){ memset(dis,0x3f3f3f,sizeof(dis)); vis[s]=1; dis[s]=0; queue<int> p; p.push(s); while(!p.empty()){ int x=p.front(); p.pop(); vis[x]=0; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+z[i].w){ dis[y]=dis[x]+z[i].w; if(!vis[y]){ tot[y]++; vis[y]=1; if(tot[y]==n+1) return false; p.push(y); } } } } return true; } signed main(){ cin>>n>>m; for(int i=1;i<=m;i++){ int a,b,c; scanf("%lld%lld%lld",&a,&b,&c); add(b,a,c); } for(int i=1;i<=n;i++) add(0,i,0); if(SPFA(0)){ for(int i=1;i<=n;i++){ cout<<dis[i]<<" "; } } else{ cout<<"NO"; } }
-
同余最短路ARC084B
#include<bits/stdc++.h> using namespace std; int K; struct node{ int to,nxt,w; }z[2000004]; int h[2000004]; int cnt; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; z[cnt].w=w; } int dis[10000004]; int vis[2000004]; typedef pair<int,int> pii; signed main(){ cin>>K; for(int i=1;i<=K;i++){ for(int j=0;j<=9;j++){ add(i,((i-1)*10+j)%K+1,j); } } for(int i=1;i<=9;i=i+1){ add(0,i+1,i); } int s=0; memset(dis,0x3f3f3f,sizeof dis); dis[s]=0; priority_queue<pii,vector<pii>,greater<pii> > p; p.push({0,s}); while(!p.empty()){ int x=p.top().second; p.pop(); if(vis[x]) continue; vis[x]=1; // cout<<x<<endl; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+z[i].w){ dis[y]=dis[x]+z[i].w; p.push({dis[y],y}); } } } cout<<dis[1]; }
网络流
点击查看
-
最小割 狼抓兔子
(最短路求法)
#include<bits/stdc++.h> #define int long long using namespace std; int n,m; struct Edge{ int to,nxt,w; }z[50000004]; int cnt; int h[20000005]; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; z[cnt].w=w; } int S=0,T; void Init(){ int w; cin>>n>>m; T=(n-1)*(m-1)*2+1; for(int i=1;i<m;i++){ cin>>w; add(S,i,w); } for(int i=2;i<n;i++){ int lst=(i-1)*(m-1)*2; for(int j=1;j<m;j++){ cin>>w; int a=lst-(m-1-j); // cout<<a<<" "<<a+(m-1)<<endl; add(a,a+(m-1),w); add(a+(m-1),a,w); } } for(int i=1;i<m;i++){ cin>>w; add(T-1-(m-1-i),T,w); /// cout<<T-1-(m-1-i)<<" "; } //puts(" "); for(int i=1;i<n;i++){ cin>>w; add((i-1)*(m-1)*2+(m-1)+1,T,w); //cout<<endl<<(i-1)*(m-1)*2+(m-1)+1<<endl; for(int j=2;j<m;j++){ cin>>w; add((i-1)*(m-1)*2+j-1,(i-1)*(m-1)*2+j-1+m,w); add((i-1)*(m-1)*2+j-1+m,(i-1)*(m-1)*2+j-1,w); // cout<<endl<<(i-1)*(m-1)*2+j-1<<" "<<(i-1)*(m-1)*2+j-1+m<<endl; } cin>>w; add(S,(i-1)*(m-1)*2+(m-1),w); // cout<<endl<<(i-1)*(m-1)*2+(m-1)<<endl; } // puts("o"); for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ cin>>w; add((i-1)*(m-1)*2+j,(i-1)*(m-1)*2+j+(m-1),w); add((i-1)*(m-1)*2+j+(m-1),(i-1)*(m-1)*2+j,w); // cout<<(i-1)*(m-1)*2+j<<" "<<(i-1)*(m-1)*2+j+(m-1)<<endl; } } } typedef pair<int,int> pii; int vis[20000004]; int dis[20000004]; priority_queue<pii,vector<pii>,greater<pii> > p; void Dijie(){ for(int i=0;i<=T;i++) dis[i]=1e18; dis[S]=0; p.push({0,S}); while(!p.empty()){ int x=p.top().second; p.pop(); if(vis[x]) continue; vis[x]=1; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(dis[y]>dis[x]+z[i].w){ dis[y]=dis[x]+z[i].w; p.push({dis[y],y}); } } } } signed main(){ Init(); Dijie(); cout<<dis[T]; }
-
最小割最大流模板 P3376
#include<bits/stdc++.h> #define int long long using namespace std; const int inf=1e9; int n,m,s,t; int u,v,w; int h[2000004]; struct node{ int to,nxt,w; }z[2000004]; int dis[2000004]; int cnt=1; int cur[2000004]; void add(int a,int b,int w){ z[++cnt].to=b; z[cnt].nxt=h[a]; h[a]=cnt; z[cnt].w=w; z[++cnt].to=a; z[cnt].nxt=h[b]; h[b]=cnt; z[cnt].w=0; } bool bfs(){ for(int i=1;i<=n;i++) dis[i]=0; queue<int> p; p.push(s); dis[s]=1; while(!p.empty()){ int x=p.front(); p.pop(); for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(z[i].w&&!dis[y]){ p.push(y); dis[y]=dis[x]+1; if(y==t) return 1; } } } return 0; } int dfs(int x,int flow){ if(x==t) return flow; int res=flow; for(int i=cur[x];i&&res;i=z[i].nxt){ int y=z[i].to; cur[x]=i; if(dis[y]==dis[x]+1&&z[i].w){ int k=dfs(y,min(res,z[i].w)); if(!k) dis[y]=0; z[i].w-=k; z[i^1].w+=k; res-=k; } } return flow-res; } signed main(){ cin>>n>>m>>s>>t; for(int i=1;i<=m;i++){ cin>>u>>v>>w; add(u,v,w); } int flo=0,maxx=0; while(bfs()){ for(int i=1;i<=n;i++) cur[i]=h[i]; while(flo=dfs(s,(1<<29))){ maxx+=flo; } } cout<<maxx; }
-
最小费用最大流 P3381
(迪杰斯特拉)
#include<bits/stdc++.h> using namespace std; int n,m,s,t; int u,v,w,c; int cnt=1; int head[1000004]; int h[1000004]; int cur[1000004]; struct node{ int to,nxt,w,c; }z[2000004]; void add(int x,int y,int w,int c){ z[++cnt].to=y; z[cnt].nxt=head[x]; head[x]=cnt; z[cnt].c=c; z[cnt].w=w; z[++cnt].to=x; z[cnt].nxt=head[y]; head[y]=cnt; z[cnt].w=0; z[cnt].c=-c; } bool vis[1000004]; int dis[1000004]; void SPFA(){ memset(h,0x3f3f3f3f,sizeof h); queue<int> p; p.push(s); vis[s]=1; while(!p.empty()){ int x=p.front(); p.pop(); vis[x]=0; for(int i=head[x];i;i=z[i].nxt){ int y=z[i].to; if(z[i].w&&h[y]>h[x]+z[i].c){ h[y]=h[x]+z[i].c; if(!vis[y]){ vis[y]=1; p.push(y); } } } } } typedef pair<int,int> pii; int ans1,ans2; const int inf=0x3f3f3f3f; bool dijie(){ memset(dis,inf,sizeof dis); memset(vis,0,sizeof vis); priority_queue<pii,vector<pii>,greater<pii> > p; dis[s]=0; p.push({0,s}); while(!p.empty()){ int x=p.top().second; p.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=z[i].nxt){ int y=z[i].to; if(z[i].w&&dis[y]>dis[x]+z[i].c+h[x]-h[y]){ dis[y]=dis[x]+h[x]-h[y]+z[i].c; p.push({dis[y],y}); } } } return dis[t]!=inf; } int dfs(int x,int flow){ int res=flow; if(x==t) return flow; vis[x]=1; for(int i=cur[x];i;i=z[i].nxt){ cur[x]=i; int y=z[i].to; if(z[i].w&&h[y]==h[x]+z[i].c&&!vis[y]){ int k=dfs(y,min(res,z[i].w)); z[i].w-=k; z[i^1].w+=k; res-=k; ans2+=k*z[i].c; if(!res) break; } } vis[x]=0; return flow-res; } signed main(){ ios::sync_with_stdio(false); cin>>n>>m>>s>>t; for(int i=1;i<=m;i++){ cin>>u>>v>>w>>c; add(u,v,w,c); } SPFA(); while(dijie()){ for(int i=1;i<=n;i++) cur[i]=head[i],vis[i]=0,h[i]+=dis[i]; ans1+=dfs(s,inf); } cout<<ans1<<" "<<ans2<<endl; }
(SPFA)
#include<bits/stdc++.h> using namespace std; struct node{ int nxt,to,w,dis; }z[100003]; int minncost,maxxflow; int s,t,e; int h[1000003]; int pre[1000003]; int last[1000003]; int flow[1000003]; int dis[1000003]; int vis[1000003]; int cnt=1; void add(int u,int v,int w,int dis){ cnt++; z[cnt].to=v; z[cnt].nxt=h[u]; z[cnt].dis=dis; z[cnt].w=w; h[u]=cnt; } bool SPFA(){ memset(dis,0x7f7f7f7f,sizeof dis); memset(vis,0,sizeof(vis)); memset(flow,0x7f7f7f7f,sizeof flow); dis[s]=0; vis[s]=1; pre[e]=-1; queue<int> p; p.push(s); while(!p.empty()){ int x=p.front(); p.pop(); vis[x]=0; for(int i=h[x];i!=-1;i=z[i].nxt){ int y=z[i].to; int w=z[i].dis; if(dis[y]>dis[x]+w&&z[i].w){ pre[y]=x; last[y]=i; flow[y]=min(flow[x],z[i].w); dis[y]=dis[x]+w; if(!vis[y]){ vis[y]=1; p.push(y); } } } } if(dis[e]!=0x7f7f7f7f)return 1; return 0; } void MCMF(){ while(SPFA()){ int u=e; maxxflow+=flow[u]; minncost+=flow[u]*dis[u]; while(u!=s){ z[last[u]].w-=flow[e]; z[last[u]^1].w+=flow[e]; u=pre[u]; } } } int main(){ int n,m; scanf("%d%d%d%d",&n,&m,&s,&e); for(int i=1;i<=n;i++) h[i]=-1; for(int i=1;i<=m;i++){ int u,v,f,w; scanf("%d%d%d%d",&u,&v,&f,&w); add(u,v,f,w); add(v,u,0,-w); } MCMF(); cout<<maxxflow<<" "<<minncost; }
-
最小路径覆盖P2764
#include<bits/stdc++.h> using namespace std; int n,m; int x,y; struct node{ int to,nxt,w; }z[20000004]; int cnt=1; int h[10000004]; int s,t; int dis[10000004]; int cur[10000004]; void add(int x,int y,int w){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; z[cnt].w=w; z[++cnt].to=x; z[cnt].nxt=h[y]; h[y]=cnt; z[cnt].w=0; } bool BFS(){ for(int i=1;i<=t;i++) dis[i]=0; queue<int> p; p.push(s); dis[s]=1; while(!p.empty()){ int x=p.front(); p.pop(); for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(z[i].w&&!dis[y]){ //cout<<"o\n"; p.push(y); dis[y]=dis[x]+1; if(y==t) return 1; } } } return 0; } int maxx; int dfs(int x,int flow){ if(x==t) return flow; int res=flow; for(int i=cur[x];i&&res;i=z[i].nxt){ int y=z[i].to; cur[x]=i; if(z[i].w&&dis[y]==dis[x]+1){ int k=dfs(y,min(res,z[i].w)); if(!k) dis[y]=0; z[i].w-=k; z[i^1].w+=k; res-=k; } } return flow-res; } int flo; void Dinic(){ while(BFS()){ for(int i=0;i<=t;i++) cur[i]=h[i]; while(flo=dfs(s,(1<<29))) maxx+=flo; } } int fa[10000004]; int find(int x){ if(x==fa[x]) return x; else return fa[x]=find(fa[x]); } void merge(int x,int y){ int fx=find(fa[x]); int fy=find(fa[y]); if(fx!=fy) fa[fx]=fy; } signed main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>x>>y; add(x,y+n,1); } s=0,t=(n<<1)+1; for(int i=1;i<=n;i++){ add(s,i,1); add(i+n,t,1); } Dinic(); int ans=n-maxx; for(int i=1;i<=t;i++) fa[i]=i; for(int i=1;i<=n;i++){ for(int j=h[i];j;j=z[j].nxt){ int y=z[j].to; if(!z[j].w&&y-n<=n&&y){ merge(i,y-n); } } } for(int i=n;i;i--){ bool flag=0; for(int j=1;j<=n;j++){ if(find(j)==i){ cout<<j<<" "; flag=1; } }if(flag) cout<<"\n"; } cout<<ans<<"\n"; }
欧拉回路
点击查看
-
欧拉回路
#include <bits/stdc++.h> #define int long long using namespace std; int t; int n, m; int a, b; int in[200004]; int out[200004]; struct node { int to, nxt, id; } z[4000004]; int sum[4000004]; int h[2000004]; int cnt; void add(int x, int y, int id) { z[++cnt].to = y; z[cnt].nxt = h[x]; h[x] = cnt; z[cnt].id = id; } int num; int ans[200004]; bool vis[200004]; typedef pair<int, int> pii; vector<pii> v[200004]; void dfs(int x) { for (int &i = h[x]; i; i = z[i].nxt) { int y = z[i].to; int id = z[i].id; if (vis[abs(id)]) continue; vis[abs(id)] = 1; dfs(y); ans[++num] = id; } } bool flag = 0; bool check() { int s = 1; for (int i = 1; i <= n; i++) { if (t == 1) { if ((in[i] + out[i]) & 1) return 0; if (in[i] + out[i]) s = i; } else { if (in[i] != out[i]) return 0; if (in[i]) s = i; } } dfs(s); if (num < m) return 0; return 1; } signed main() { cin >> t; cin >> n >> m; for (int i = 1; i <= m; i++) { cin >> a >> b; add(a, b, i); if (t == 1) add(b, a, -i); in[b]++; out[a]++; } if (!check()) { cout << "NO"; return 0; } cout << "YES\n"; for (int i = num; i >= 1; i--) cout << ans[i] << " "; }
\(\Large{树论}\)
点击查看
树的直径
点击查看
-
B4016 树的直径
#include<bits/stdc++.h> using namespace std; int n,a,b; struct node{ int to,nxt; }z[1000004]; int cnt; int h[1000040]; void add(int x,int y){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; } int id,maxx; int dis[2000004]; void dfs(int x,int fa){ if(dis[x]>maxx){ maxx=dis[x]; id=x; } for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(y==fa) continue; else{ dis[y]=dis[x]+1; dfs(y,x); } } } int main(){ cin>>n; for(int i=1;i<n;i++){ cin>>a>>b; add(a,b); add(b,a); } dfs(1,0); memset(dis,0,sizeof dis); maxx=0; dfs(id,0); cout<<maxx; }
LCA
点击查看
-
P3379 【模板】最近公共祖先(LCA)
倍增:
#include<bits/stdc++.h> using namespace std; int n,m,s; int f[500005][21]; int d[500002]; vector<int> g[5000070]; void dfs(int x,int fa){ f[x][0]=fa; d[x]=d[fa]+1; for(int i=0;i<g[x].size();i++){ if(g[x][i]==fa) continue; dfs(g[x][i],x); } } void gh(){ for(int j=1;j<=20;j++){ for(int i=1;i<=n;i++){ f[i][j]=f[f[i][j-1]][j-1]; } } } int lca(int x,int y){ if(d[x]<d[y]) swap(x,y); for(int i=20;i>=0;i--){ if(d[f[x][i]]>=d[y]) x=f[x][i]; } if(x==y){ return y; } for(int i=20;i>=0;i--){ if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; } return f[x][0]; } int main(){ cin>>n>>m>>s; for(int i=1;i<n;i++){ int x,y; cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } dfs(s,0); gh(); for(int i=1;i<=m;i++){ int a,b; cin>>a>>b; cout<<lca(a,b)<<endl; } }
树剖:
#include<bits/stdc++.h> using namespace std; int n,m,s; int cnt; struct node{ int to,nxt; }z[1200000]; struct lian{ int fa,top,num,son,maxxson,dep; }l[500006]; int h[500004]; void add(int x,int y){ z[++cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; } void dfs(int x,int fa){ l[x].fa=fa; l[x].dep=l[fa].dep+1; l[x].son=1; l[l[x].maxxson].son=-1; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(y==fa) continue; dfs(y,x); l[x].son+=l[y].son; if(l[y].son>l[l[x].maxxson].son){ l[x].maxxson=y; l[l[x].maxxson].son=l[y].son; } } } int id; void dfs1(int x,int fa,int top){ l[x].top=top; l[x].num=++id; if(!l[x].maxxson) return ; dfs1(l[x].maxxson,x,top); for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(y==fa||y==l[x].maxxson) continue; else{ dfs1(y,x,y); } } } int lca(int a,int b){ while(l[a].top!=l[b].top){ if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b); a=l[l[a].top].fa; } if(l[a].dep>l[b].dep){ swap(a,b); } return a; } int main(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } l[0].dep=0; dfs(s,0); dfs1(s,0,s); while(m--){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } }
\(\Large{数据结构}\)
点击查看
树链剖分
点击查看
-
P3384 【模板】重链剖分/树链剖分
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; struct node{ int to,nxt; }z[N]; struct tree{ int l,r,lazy,sum; }t[4*N]; struct good{ int w,fa,top,id,d,son,maxson; }l[N]; int n,m,root,mod,ans; int h[N]; int a[N]; int w[N]; int cnt,res; void add(int x,int y){ cnt++; z[cnt].to=y; z[cnt].nxt=h[x]; h[x]=cnt; } void dfs1(int x,int fa,int dis){ l[x].son=1; l[x].fa=fa; l[x].d=dis; l[l[x].maxson].son=-1; for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(y==fa) continue; dfs1(y,x,dis+1); l[x].son+=l[y].son; if(l[y].son>l[l[x].maxson].son)l[x].maxson=y,l[l[x].maxson].son=l[y].son; } } void dfs2(int x,int topf){ l[x].id=++cnt; w[cnt]=a[x]; l[x].top=topf; if(!l[x].maxson)return; dfs2(l[x].maxson,topf); for(int i=h[x];i;i=z[i].nxt){ int y=z[i].to; if(y==l[x].fa||y==l[x].maxson)continue; dfs2(y,y); } } void build(int l,int r,int p){ t[p].l=l; t[p].r=r; if(l==r){ t[p].sum=w[l]; t[p].sum%=mod; return ; } int mid=(l+r)>>1; build(l,mid,p*2); build(mid+1,r,p*2+1); t[p].sum=t[p*2].sum+t[p*2+1].sum; t[p].sum%=mod; } void lazzy(int x){ if(t[x].lazy){ t[x*2].sum+=t[x].lazy*(t[x*2].r-t[x*2].l+1); t[x*2+1].sum+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1); t[x*2].lazy+=t[x].lazy; t[x*2+1].lazy+=t[x].lazy; t[x*2].sum%=mod; t[x*2+1].sum%=mod; t[x*2+1].lazy%=mod; t[x*2].lazy%=mod; t[x].lazy=0; } } int qury(int L,int R,int p){ int res=0; if(t[p].l>=L&&t[p].r<=R) { return t[p].sum; } lazzy(p); int mid=t[p].l+t[p].r>>1; if(L<=mid){ res+=qury(L,R,p*2); } if(R>mid){ res+=qury(L,R,p*2+1); } return res%mod; } void chan(int l,int r,int k,int p){ if(t[p].l>=l&&t[p].r<=r){ t[p].lazy+=k; t[p].sum+=k*(t[p].r-t[p].l+1); t[p].sum%=mod; t[p].lazy%=mod; return ; } lazzy(p); int mid=t[p].r+t[p].l>>1; if(l<=mid){ chan(l,r,k,p*2); } if(r>mid){ chan(l,r,k,p*2+1); } t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod; } int find(int x,int y){ int ans=0; while(l[x].top!=l[y].top){ if(l[l[x].top].d<l[l[y].top].d){ } ans+=qury(l[l[x].top].id,l[x].id,1); ans=ans%mod; x=l[l[x].top].fa; } if(l[x].d>l[y].d) swap(x,y); ans+=qury(l[x].id,l[y].id,1); return ans%mod; } void geng2(int x,int z){ chan(l[x].id,l[x].id+l[x].son-1,z,1); } void geng(int x,int y,int z){ z=z%mod; while(l[x].top!=l[y].top){ if(l[l[x].top].d<l[l[y].top].d){ swap(x,y); } chan(l[l[x].top].id,l[x].id,z,1); x=l[l[x].top].fa; } if(l[x].d>l[y].d){ swap(x,y); } chan(l[x].id,l[y].id,z,1); } int find2(int x){ ans=0; ans=qury(l[x].id,l[x].id+l[x].son-1,1); return ans%mod; } int main(){ scanf("%d%d%d%d",&n,&m,&root,&mod); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[i]%=mod; } for(int i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(root,0,1); cnt=0; dfs2(root,root); build(1,n,1); for(int i=1;i<=m;i++){ int opt; scanf("%d",&opt); if(opt==1){ int x,y,z; scanf("%d%d%d",&x,&y,&z); geng(x,y,z); } if(opt==2){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",find(x,y)); } if(opt==3){ int x,z; scanf("%d%d",&x,&z); geng2(x,z); } if(opt==4){ int x; scanf("%d",&x); printf("%d\n",find2(x)); } } }
\(\Large{字符串}\)
点击查看
Z 函数
点击查看
-
P5410 【模板】扩展 KMP/exKMP(Z 函数)
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e7+10; char a[N],b[N]; int ans; int z[N]; int p[N]; signed main(){ ios::sync_with_stdio(false); cin>>(a+1)>>(b+1); int l=0,r=0; z[1]=strlen(b+1); for(int i=2;i<=strlen(b+1);i++){ if(i<r) z[i]=min(z[i-l+1],r-i+1); while(i+z[i]<=strlen(b+1)&&b[i+z[i]]==b[z[i]+1]) { z[i]++; } if(r<i+z[i]-1){ r=i+z[i]-1; l=i; } } for(int i=1;i<=strlen(b+1);i++){ ans=ans^(i*(z[i]+1)); } cout<<ans<<endl; l=0,r=0; for(int i=1;i<=strlen(a+1);i++){ if(i<r) p[i]=min(z[i-l+1],r-i+1); while(i+p[i]<=strlen(a+1)&&a[i+p[i]]==b[p[i]+1]) { p[i]++; } if(r<i+p[i]-1){ r=i+p[i]-1; l=i; } } ans=0; for(int i=1;i<=strlen(a+1);i++){ ans^=(i*(p[i]+1)); } cout<<ans; }
AC 自动机
点击查看
-
P5357 【模板】AC 自动机
#include<bits/stdc++.h> using namespace std; int n; const int N=200007; string s; int fail[N]; int num; int trie[N][30]; int End[N]; int in[N]; vector<int> v[N]; int val[N]; void insert(int id){ int p=0; for(int i=0;i<s.size();i++){ if(!trie[p][s[i]-'a']) trie[p][s[i]-'a']=++num; p=trie[p][s[i]-'a']; } End[id]=p; } void build(){ queue<int> p; for(int i=0;i<26;i++){ if(trie[0][i]){ fail[trie[0][i]]=0; p.push(trie[0][i]); } } while(!p.empty()){ int x=p.front(); p.pop(); for(int i=0;i<26;i++){ if(trie[x][i]){ fail[trie[x][i]]=trie[fail[x]][i]; p.push(trie[x][i]); } else{ trie[x][i]=trie[fail[x]][i]; } } } } void ACZDJ(){ int p=0; for(int i=0;i<s.size();i++){ p=trie[p][s[i]-'a']; val[p]++; } return ; } signed main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>s; insert(i); } build(); for(int i=1;i<=num;i++){ v[i].push_back(fail[i]); in[fail[i]]++; } cin>>s; ACZDJ(); queue<int> Q; for(int i=0;i<=num;i++){ if(!in[i]) Q.push(i);; } while(!Q.empty()){ int x=Q.front(); Q.pop(); for(int i=0;i<v[x].size();i++){ int y=v[x][i]; in[y]--; val[y]+=val[x]; if(!in[y]) Q.push(y); } } for(int i=1;i<=n;i++) { cout<<val[End[i]]<<"\n"; } }
后缀数组 SA
点击查看
-
P3809 【模板】后缀排序
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; char s[N]; int m,p,n; int rk[N<<1],sa[N<<1],ork[N<<1],id[N],cnt[N]; signed main(){ cin>>(s+1); n=strlen(s+1); m=127; for(int i=1;i<=n;i++) ++cnt[rk[i]=s[i]]; for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i; memcpy(ork+1,rk+1,n*sizeof(int)); for(int i=1;i<=n;i++){ if(ork[sa[i]]==ork[sa[i-1]]) rk[sa[i]]=p; else rk[sa[i]]=++p; } for(int w=1;w<n;w<<=1,m=n){ // int cur=0; memset(cnt,0,sizeof cnt); memcpy(id+1,sa+1,n*sizeof(int)); for(int i=1;i<=n;i++) ++cnt[rk[id[i]+w]]; for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--) sa[cnt[rk[id[i]+w]]--]=id[i]; memset(cnt,0,sizeof cnt); memcpy(id+1,sa+1,n*sizeof(int)); for(int i=1;i<=n;i++) ++cnt[rk[id[i]]]; for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--) sa[cnt[rk[id[i]]]--]=id[i]; memcpy(ork+1,rk+1,n*sizeof(int)); p=0; for(int i=1;i<=n;i++){ if(ork[sa[i]]==ork[sa[i-1]]&&ork[sa[i]+w]==ork[sa[i-1]+w]) rk[sa[i]]=p; else rk[sa[i]]=++p; } } for(int i=1;i<=n;i++) cout<<sa[i]<<" "; }