noip考前模板复习
网络流
Dinic(搭配飞行员)
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100+10,maxs=maxn*maxn+2*maxn;
int n,m,S,T;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int x,y,cap,flow;
Node(){}
Node(int x,int y,int cap):x(x),y(y),cap(cap){}
}node[maxs];
int fir[maxn],nxt[maxs],e=1,cur[maxn];
void add(int x,int y,int z) {
node[++e]=Node(x,y,z); nxt[e]=fir[x];fir[x]=e;
node[++e]=Node(y,x,0); nxt[e]=fir[y];fir[y]=e;
}
int dis[maxn],zz[maxn];
bool bfs() {
int s=1,t=0,x,y,z;
memset(dis,-1,sizeof(dis));
memset(zz,0,sizeof(zz));
dis[S]=0; zz[++t]=S;
while(s<=t) {
x=zz[s++];
for(y=fir[x];y;y=nxt[y]) {
if(node[y].flow>=node[y].cap||dis[z=node[y].y]!=-1) continue;
dis[z]=dis[x]+1; zz[++t]=z;
}
}
return dis[T]!=-1;
}
int dfs(int pos,int maxf) {
if(pos==T||!maxf) return maxf;
int rs=0,now,z;
for(int &y=cur[pos];y;y=nxt[y]) {
if(node[y].flow>=node[y].cap||dis[z=node[y].y]!=dis[pos]+1) continue;
now=dfs(z,min(node[y].cap-node[y].flow,maxf));
node[y].flow+=now;
node[y^1].flow-=now;
rs+=now; maxf-=now;
}
if(!rs) dis[pos]=-1;
return rs;
}
int Dinic() {
int rs=0;
while(bfs()) {
memcpy(cur,fir,sizeof(fir));
rs+=dfs(S,0x3f3f3f3f);
}
return rs;
}
int main() {
n=read(); m=read();
S=n+1; T=S+1; int x,y;
for(int i=1;i<=m;++i) add(S,i,1);
for(int i=m+1;i<=n;++i) add(i,T,1);
while(scanf("%d%d",&x,&y)==2) add(x,y,1);
printf("%d",Dinic());
return 0;
}
MCMF(餐巾计划)
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=2000+10,maxm=4*maxn,INF=0x3f3f3f3f;
int n,P,M,F,N,R,S,T;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int x,y,cap,flow,w;
Node(){}
Node(int x,int y,int cap,int w):x(x),y(y),cap(cap),w(w){}
}node[2*maxm];
int fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,int z,int w) {
node[++e]=Node(x,y,z,w); nxt[e]=fir[x];fir[x]=e;
node[++e]=Node(y,x,0,-w);nxt[e]=fir[y];fir[y]=e;
}
int from[maxn],zz[maxn],dis[maxn];
bool vis[maxn];
bool spfa() {
int s=1,t=0,x,y,z;
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(zz,0,sizeof(zz));
zz[++t]=S;dis[S]=0;vis[S]=1;
while(s<=t) {
x=zz[s%maxn];s++;vis[x]=0;
for(y=fir[x];y;y=nxt[y]) {
if(node[y].flow>=node[y].cap||dis[z=node[y].y]<=dis[x]+node[y].w) continue;
dis[z]=dis[x]+node[y].w; from[z]=y;
if(!vis[z]) {
vis[z]=1;t++;
zz[t%maxn]=z;
}
}
}
return dis[T]!=INF;
}
int MCMF() {
int rs=0,now;
while(spfa()) {
now=INF;
for(int i=T;i!=S;i=node[from[i]].x) now=min(now,node[from[i]].cap-node[from[i]].flow);
for(int i=T;i!=S;i=node[from[i]].x) {
node[from[i]].flow+=now;
node[from[i]^1].flow-=now;
rs+=node[from[i]].w*now;
}
}
return rs;
}
int main() {
n=read(); S=2*n+1;T=S+1; int x;
P=read();M=read();F=read();N=read();R=read();
for(int i=1;i<=n;++i) {
add(S,i+n,INF,P);
if(i+1<=n) add(i,i+1,INF,0);
if(i+M<=n) add(i,i+M+n,INF,F);
if(i+N<=n) add(i,i+N+n,INF,R);
}
for(int i=1;i<=n;++i) {
x=read();
add(S,i,x,0);
add(i+n,T,x,0);
}
printf("%d",MCMF());
return 0;
}
最短路
SPFA(SLF)
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e4+10,maxm=5e5+10,INF=2147483647;
int n,m,S;
int aa,ff;char cc;
int read() {
aa=0;ff=1;cc=getchar();
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
int fir[maxn],nxt[maxm],to[maxm],v[maxm],e=0;
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
}
int dis[maxn],zz[maxn];
bool vis[maxn];
void spfa() {
for(int i=1;i<=n;++i) dis[i]=INF;
int s=1,t=0,x,y,z,tot=1;
dis[S]=0; zz[++t]=S; vis[S]=1;
while(tot) {
x=zz[s];s=(s+1)%maxn;vis[x]=0;tot--;
for(y=fir[x];y;y=nxt[y]) {
if(dis[z=to[y]]<=dis[x]+v[y]) continue;
dis[z]=dis[x]+v[y];
if(!vis[z]) {
vis[z]=1;tot++;
if(dis[z]<=dis[zz[s]]) {s=(s-1+maxn)%maxn;zz[s]=z;}
else {t=(t+1)%maxn;zz[t]=z;}
}
}
}
}
int main() {
n=read();m=read(); S=read();
int x,y,z;
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();
add(x,y,z);
}
spfa();
for(int i=1;i<=n;++i)printf("%d ",dis[i]);
return 0;
}
Dijkstra(堆优)
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=1e4+10,maxm=5e4+10,INF=0x3f3f3f3f;
int n,m,k,S,T,ans=INF;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[2*maxm],to[2*maxm],v[2*maxm],e=0;
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
}
struct Di{
int x,y,d;
Di(){}
Di(int x,int y,int d):x(x),y(y),d(d){}
bool operator < (const Di& a) const{
return d > a.d;
}
};
priority_queue<Di> G;
int dis[maxn][13];
void Dijkstra() {
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[S][0]=0;
G.push(Di(S,0,0));
int x,y,z,l,d;
while(!G.empty()) {
x=G.top().x;l=G.top().y;d=G.top().d; G.pop();
if(d!=dis[x][l]) continue;
for(y=fir[x];y;y=nxt[y]) {
if(dis[z=to[y]][l]>dis[x][l]+v[y]) {
dis[z][l]=dis[x][l]+v[y];
G.push(Di(z,l,dis[z][l]));
}
if(l<k&&dis[z][l+1]>dis[x][l]) {
dis[z][l+1]=dis[x][l];
G.push(Di(z,l+1,dis[z][l+1]));
}
}
}
}
int main() {
n=read();m=read();k=read();
S=read()+1;T=read()+1;
int x,y,z;
for(int i=1;i<=m;++i) {
x=read()+1;y=read()+1;z=read();
add(x,y,z);
}
Dijkstra();
for(int i=0;i<=k;++i) ans=min(ans,dis[T][i]);
printf("%d",ans);
return 0;
}
最小生成树
Kruskal
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=5000+10,maxm=2e5+10;
int n,m,ans;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int x,y,z;
}node[maxm];
bool cmp(const Node& a,const Node& b) {
return a.z<b.z;
}
int fa[maxn];
int find(int x) {
return x==fa[x]? x:fa[x]=find(fa[x]);
}
void Kr() {
sort(node+1,node+m+1,cmp);
for(int i=1;i<=n;++i) fa[i]=i;
int xx,yy,tot=0;
for(int i=1;i<=m&&tot<n-1;++i) {
xx=find(node[i].x); yy=find(node[i].y);
if(xx!=yy) fa[xx]=yy,tot++,ans+=node[i].z;
}
if(tot==n-1) printf("%d",ans);
else printf("orz");
}
int main() {
n=read(); m=read();
for(int i=1;i<=m;++i) {
node[i].x=read();node[i].y=read();node[i].z=read();
}
Kr();
return 0;
}
Prim
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=5000+10,maxm=2e5+10;
int n,m;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[2*maxm],to[2*maxm],v[2*maxm],e=0;
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
}
struct Node{
int x,d;
Node(){}
Node(int x,int d):x(x),d(d){}
bool operator <(const Node& a) const {
return d > a.d;
}
};
priority_queue<Node> G;
int dis[maxn];
bool vis[maxn];
void Prim() {
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[1]=0; G.push(Node(1,0));
int x,y,z,tot=0,rs=0;
while(!G.empty()&&tot<n) {
x=G.top().x;G.pop();
if(vis[x]) continue; vis[x]=1;rs+=dis[x];tot++;
for(y=fir[x];y;y=nxt[y]) {
if(dis[z=to[y]]<=v[y]) continue;
dis[z]=v[y];
G.push(Node(z,dis[z]));
}
}
if(tot==n) printf("%d",rs);
else printf("orz");
}
int main() {
n=read(); m=read(); int x,y,z;
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();
add(x,y,z);
}
Prim();
return 0;
}
二分图匹配
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=2000+10;
int n1,n2,m,ans;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[2*maxn],nxt[maxn*maxn],to[maxn*maxn],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}
int mch[2*maxn];
bool vis[maxn];
int expd(int pos) {
int z;
for(int y=fir[pos];y;y=nxt[y]) {
if(vis[z=to[y]]) continue;
vis[z]=1;
if(!mch[z]||expd(mch[z])) {
mch[z]=pos; return 1;
}
}
return 0;
}
int main() {
n1=read();n2=read();m=read();
int x,y;
for(int i=1;i<=m;++i) {
x=read();y=read();
if(x>n1||y>n2) continue;
add(x,y+n1);
}
for(int i=1;i<=n1;++i) memset(vis,0,sizeof(vis)),ans+=expd(i);
printf("%d",ans);
return 0;
}
排序
归并排序
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=4e4+10;
int n,a[maxn],ans;
int aa,ff;char cc;
int read() {
aa=0;cc=getchar();ff=1;
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
int c[maxn];
void msort(int l,int r) {
if(l==r) return;
int mid=(l+r)>>1;
msort(l,mid);msort(mid+1,r);
int pos1=l,pos2=mid+1;
for(int i=l;i<=r;++i) {
if(pos2>r||(a[pos1]<=a[pos2]&&pos1<=mid)) c[i]=a[pos1++];
else {
ans+=mid-pos1+1;
c[i]=a[pos2++];
}
}
for(int i=l;i<=r;++i) a[i]=c[i];
}
int main() {
n=read();
for(int i=1;i<=n;++i) a[i]=read();
msort(1,n);
printf("%d",ans);
return 0;
}
字符串
KMP
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int n,m,nt[maxn];
char s[maxn],c[maxn];
int main() {
scanf("%s%s",s+1,c+1);
n=strlen(s+1); m=strlen(c+1);
c[m+1]='#';int pos;
for(int i=2;i<=m;++i) {
pos=nt[i-1];
while(pos&&c[pos+1]!=c[i]) pos=nt[pos];
nt[i]=c[pos+1]==c[i]? pos+1:0;
}
pos=0;
for(int i=1;i<=n;++i) {
while(pos&&s[i]!=c[pos+1]) pos=nt[pos];
if(s[i]==c[pos+1]) pos++;
if(pos==m) printf("%d\n",i-m+1),pos=nt[pos];
}
for(int i=1;i<=m;++i) printf("%d ",nt[i]);
return 0;
}
AC自动机
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int n;
char s[maxn];
struct Node{
int son[27],fail,sum;
}node[maxn/2];
int t;
void add() {
int now=0,len=strlen(s+1),x;
for(int i=1;i<=len;++i) {
x=s[i]-'a';
if(!node[now].son[x]) node[now].son[x]=++t;
now=node[now].son[x];
}
node[now].sum++;
}
int zz[maxn];
void bld() {
int s=1,t=0,x,y;
for(int i=0;i<26;++i) if(node[0].son[i]) zz[++t]=node[0].son[i];
while(s<=t) {
x=zz[s++];
for(int i=0;i<26;++i) {
y=node[x].son[i];
if(!y) node[x].son[i]=node[node[x].fail].son[i];
else node[y].fail=node[node[x].fail].son[i],zz[++t]=y;
}
}
}
void q() {
int len=strlen(s+1),now=0,ans=0,x,y;
for(int i=1;i<=len;++i) {
x=s[i]-'a';
now=node[now].son[x];
for(y=now;y&&~node[y].sum;y=node[y].fail) ans+=node[y].sum,node[y].sum=-1;
}
printf("%d",ans);
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%s",s+1);
add();
}
bld();
scanf("%s",s+1);
q();
return 0;
}
线性基
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=50+10;
ll n,h[maxn],now;
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
void add(ll x) {
for(int i=50;~i;--i) if((x>>i)&1) {
if(h[i]) x^=h[i];
else {
h[i]=x;
break;
}
}
}
int main() {
n=read();
for(int i=1;i<=n;++i) add(read());
for(int i=50;~i;--i) if((now^h[i])>now) now^=h[i];
printf("%lld",now);
return 0;
}
矩阵快速幂
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=5000+10;
const ll mod=1e9+7;
ll n,now[5]={0,2,2,10,32},mtx[5][5],f[5],d[5][5];
void qf() {
memset(f,0,sizeof(f));
for(int i=1;i<=4;++i) for(int k=1;k<=4;++k) (f[i]+=now[k]*mtx[k][i]%mod)%=mod;
memcpy(now,f,sizeof(f));
}
void qd() {
memset(d,0,sizeof(d));
for(int i=1;i<=4;++i) for(int j=1;j<=4;++j) for(int k=1;k<=4;++k) (d[i][j]+=mtx[i][k]*mtx[k][j]%mod)%=mod;
memcpy(mtx,d,sizeof(d));
}
void qp(ll k) {
while(k) {
if(k&1) qf();
qd(); k>>=1;
}
}
int main() {
scanf("%lld",&n);
mtx[1][1]=mtx[3][2]=mtx[4][3]=mtx[1][4]=1;
mtx[2][4]=2; mtx[3][4]=mod-5; mtx[4][4]=4;
qp(n-3);
printf("%lld",now[2]);
return 0;
}
数据结构
树状数组区间修改区间查询
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1e5+10;
ll n,m,a[maxn],g[maxn],h[maxn],ans;
ll aa,ff;char cc;
ll read() {
aa=0;cc=getchar();ff=1;
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
void add(int pos,ll x,ll *sz) {
while(pos<=n) {
sz[pos]+=x;
pos+=(pos&-pos);
}
}
ll q(int pos,ll *sz) {
ll rs=0;
while(pos) {
rs+=sz[pos];
pos-=(pos&-pos);
}
return rs;
}
int main() {
n=read(); m=read(); int op;ll l,r,x;
for(int i=1;i<=n;++i) {
a[i]=read();
add(i,a[i]-a[i-1],g);
add(i,(ll)(i-1)*(a[i]-a[i-1]),h);
}
for(int i=1;i<=m;++i) {
op=read(); l=read(); r=read();
if(op==1) {
x=read();
add(l,x,g);add(r+1,-x,g);
add(l,(ll)(l-1)*x,h);
add(r+1,(ll)r*(-x),h);
}
else {
ans=r*q(r,g)-q(r,h)-(l-1)*q(l-1,g)+q(l-1,h);
printf("%lld\n",ans);
}
}
return 0;
}
Tarjan
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e4+10,maxm=1e5+10;
int n,m,v[maxn],totans;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[maxm],to[maxm],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
}
int ff[maxn],nn[maxm],tt[maxm],ee=0,ind[maxn];
void add2(int x,int y) {
tt[++ee]=y;nn[ee]=ff[x];ff[x]=ee;ind[y]++;
}
int id[maxn],d,zz[maxn],t,top[maxn];
int xd[maxn],sum[maxn],totd;
bool vis[maxn],inz[maxn];
void tj(int pos) {
id[pos]=top[pos]=++d;
vis[pos]=inz[pos]=1; zz[++t]=pos;
int y,z;
for(y=fir[pos];y;y=nxt[y]) {
if(inz[z=to[y]]) top[pos]=min(top[pos],top[z]);
if(vis[z]) continue;
tj(z); top[pos]=min(top[pos],top[z]);
}
if(top[pos]==id[pos]) {
totd++;
while(t) {
xd[y=zz[t]]=totd;
sum[totd]+=v[y];
inz[y]=0;
if(zz[t--]==pos) break;
}
}
}
int ans[maxn];
void tp() {
int s=1,t=0,x,y,z;
for(int i=1;i<=totd;++i) if(!ind[i]) zz[++t]=i,ans[i]=sum[i];
while(s<=t) {
x=zz[s++];
for(y=ff[x];y;y=nn[y]) {
ind[z=tt[y]]--;
ans[z]=max(ans[z],sum[z]+ans[x]);
if(!ind[z]) zz[++t]=z;
}
}
}
int main() {
n=read();m=read(); int x,y;
for(int i=1;i<=n;++i) v[i]=read();
for(int i=1;i<=m;++i) {
x=read();y=read();
add(x,y);
}
for(int i=1;i<=n;++i) if(!vis[i]) tj(i);
for(int i=1;i<=n;++i) {
for(y=fir[i];y;y=nxt[y]) if(xd[x=to[y]]!=xd[i]){
add2(xd[i],xd[x]);
}
}
tp();
for(int i=1;i<=totd;++i) totans=max(totans,ans[i]);
printf("%d",totans);
return 0;
}
弱者就是会被欺负呀