这是小小得整理,虽然还没有弄完,但是还是有一个样子了~
慢慢整理不用急
ACM
模板库
目录
一、图论
1.Spfa
(1).最短路
(2).次短路
2.强连通
(1).出入度操作
3.并查集
(1).简单并查集
(2).功能并查集
(3).倒推并查集
4.网络流
(1).简单构图
(2).复杂构图
二、树
1.树状数组
2.线段树
(1)维护只增数组
(2)维护定量数组
(3)Lazy维护
3.伸展树
4.最小生成树
(1)K算法
三、数论
1.快速幂
(1).gcd
(2).exgcd
(3).矩阵乘法
四、搜索
1.Dfs
(1).简单
(2).复杂
五、DP
1. 一维
(1).简单
(2).复杂
2. 二维
(1).简单
(2).复杂
1.图论——Spfa
(1).最短路
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y,c,next;
}a[210000];int len,first[5100];
bool v[5100];
int n,m;int d[5100],head,tail,list[5100];
void ins(int x,int y,int c){
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=first[x];first[x]=len;
}
void spfa(int st,int ed){
memset(v,false,sizeof(v));v[st]=true;
memset(d,63,sizeof(d));d[st]=0;
head=1;tail=2;list[head]=st;
while(head!=tail){
int x=list[head];
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(d[y]>d[x]+a[k].c){
d[y]=d[x]+a[k].c;
if(v[y]==false){
v[y]=true;
list[tail++]=y;
if(tail==n+1)tail=1;
}
}
}
v[x]=false;
head++;if(head==n+1)head=1;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
}
spfa(1,n);
printf("%d\n",d[n]);
return 0;
}
(2).次短路
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y,c,next;
}a[210000];int len,first[5100];
bool v[5100];
int n,m;int d[5100],dd[5100],head,tail,list[5100];
void ins(int x,int y,int c){
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=first[x];first[x]=len;
}
void spfa(int st,int ed){
memset(v,false,sizeof(v));v[st]=true;
memset(d,63,sizeof(d));d[st]=0;
head=1;tail=2;list[head]=st;
while(head!=tail){
int x=list[head];
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(d[y]>d[x]+a[k].c){
dd[y]=d[y];d[y]=d[x]+a[k].c;
if(v[y]==false){
v[y]=true;
list[tail++]=y;if(tail==n+1)tail=1;
}
}
if(dd[x]!=-1&&(dd[y]==-1||dd[y]>dd[x]+a[k].c)){
dd[y]=dd[x]+a[k].c;
if(v[y]==false){
v[y]=true;
list[tail++]=y;if(tail==n+1)tail=1;
}
}
else if(d[x]+a[k].c!=d[y]&&(dd[y]==-1||dd[y]>d[x]+a[k].c)){
dd[y]=d[x]+a[k].c;
if(v[y]==false){
v[y]=true;
list[tail++]=y;if(tail==n+1)tail=1;
}
}
}
v[x]=false;
head++;if(head==n+1)head=1;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
}
spfa(1,n);
printf("%d\n",dd[n]);
return 0;
}
2.图论——强连通
(1).出入度操作
#include<set>
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y,next;
}a[110000];int len,first[11000],n,m;
void ins(int x,int y){
len++;a[len].x=x;a[len].y=y;
a[len].next=first[x];first[x]=len;
}
int sta[11000],tp;bool v[11000];
int cnt,belong[11000];
int low[11000],dfn[11000],id,num[11000];
int chu[11000],ru[11000];
void dfs(int x){
low[x]=dfn[x]=++id;
sta[++tp]=x;v[x]=true;
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(dfn[y]==0){
dfs(y);
if(low[x]>low[y])low[x]=low[y];
}
else if(v[y]==true){
if(low[x]>dfn[y])low[x]=dfn[y];
}
}
if(low[x]==dfn[x]){
cnt++;
int i;
do{
i=sta[tp--];
belong[i]=cnt;
v[i]=false;
}while(i!=x);
}
}
int main(){
scanf("%d%d",&n,&m);
len=0;memset(first,false,sizeof(first));
cnt=0;memset(v,false,sizeof(v));
memset(dfn,0,sizeof(dfn));
tp=id=cnt=0;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);
}
for(int i=1;i<=n;i++)if(dfn[i]==0)dfs(i);
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)num[belong[i]]++;
for(int i=1;i<=len;i++){
if(belong[a[i].x]!=belong[a[i].y]){
chu[belong[a[i].x]]++;
ru[belong[a[i].y]]++;
}
}
if(cnt==1){printf("%d\n",n);return 0;}
int ans,zs=0;
for(int i=1;i<=cnt;i++){
if(chu[i]==0){
zs++;ans=i;
}
}
if(zs==1)printf("%d\n",num[ans]);
else printf("0\n");
}
3.图论——并查集
(1).简单并查集
(2).功能并查集
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,fa[1100000];
bool v[1100000];
int findfa(int x){
if(x==fa[x])return x;
else return fa[x]=findfa(fa[x]);
}
void up(int x,int y){
if(x<y)swap(x,y);
v[y]=true;
fa[y]=x;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n+1;i++)fa[i]=i;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
int fx=findfa(x),fy=findfa(y);
if(fx==fy)v[fx]=true;
else up(fx,fy);
}
for(int i=1;i<=n+1;i++){
if(v[i]==false){
printf("%d\n",i-1);
return 0;
}
}
return 0;
}
(3).倒推并查集
#include<set>
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,next;
}a[510000];//结构体,表示连接到x这个点
int n,m,k,len,sum,f[510000],first[510000],fa[510000],ans[510000];
bool v[510000],b[510000];
void ins(int x,int y){
len++;a[len].x=y;a[len].next=first[x];first[x]=len;
len++;a[len].x=x;a[len].next=first[y];first[y]=len;//建边
}
int findfa(int x){
if(x==fa[x])return fa[x];//找祖先
return fa[x]=findfa(fa[x]);
}
void add(int x){
int xf=findfa(x);
for(int k=first[x];k>0;k=a[k].next){ //v代表边现在存在
if(v[a[k].x]==true){
int yf=findfa(a[k].x);
if(xf!=yf){
fa[yf]=x;sum--;//如果祖先不一样的话,统一祖先,联通块-1
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)fa[i]=i;
len=0;memset(first,0,sizeof(first));
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);//建边不解释
}
scanf("%d",&k);
memset(b,false,sizeof(b));
memset(v,false,sizeof(v));
for(int i=1;i<=k;i++){
scanf("%d",&f[i]);
b[f[i]]=true;//如果不会被炸毁的先标记下来下边可以用上
}
for(int i=0;i<n;i++){//是0到n-1,好坑爹
if(b[i]==false){//没被炸毁的先建边
sum++;add(i);
v[i]=true;//建了边代表存在的
}
}
ans[k+1]=sum;//k+1代表最后炸毁的状态
for(int i=k;i>0;i--){
sum++;//好,我们再模拟,一个一个把点加上去
add(f[i]);//加点
v[f[i]]=true;//很好这条边已经存在了
ans[i]=sum;//记录值
}
for(int i=1;i<=k+1;i++)printf("%d\n",ans[i]);//输出
}
3.图论——并查集
(1). 简单构图
(2). 复杂构图
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y,c,next,other;
}a[1100000];int len,first[1100000];
int n,m,d,list[1100000],head,tail,st,ed,K[1100][1100],ans,answer,h[1100000],Nh[1100][1100],Ch[1100][1100];
char s[1100];
double pd(int x,int y,int x1,int y1){
return sqrt(double((x-x1)*(x-x1)+(y-y1)*(y-y1)));
}
void ins(int x,int y,int c){
int xx,yy;
len++;xx=len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=first[x];first[x]=len;
len++;yy=len;
a[len].x=y;a[len].y=x;a[len].c=0;
a[len].next=first[y];first[y]=len;
a[xx].other=yy;
a[yy].other=xx;
}
bool bt(){
memset(h,0,sizeof(h));h[st]=1;
list[1]=st;head=1;tail=2;
while(head!=tail){
int x=list[head];
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(a[k].c>0&&h[y]==0){
h[y]=h[x]+1;
list[tail++]=y;
}
}
head++;
}
if(h[ed]>0)return true;
else return false;
}
int findflow(int x,int f){
if(x==ed)return f;
int s=0,tmp;
for(int k=first[x];k>0;k=a[k].next){
int y=a[k].y;
if(a[k].c>0&&h[y]==h[x]+1&&s<f){
tmp=findflow(y,min(a[k].c,f-s));
s+=tmp;
a[k].c-=tmp;a[a[k].other].c+=tmp;
}
}
if(s==0)h[x]=0;
return s;
}
int main(){
scanf("%d%d%d",&n,&m,&d);
st=0;ed=10001;
len=0;memset(first,0,sizeof(first));
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
K[i][j]=s[j]-'0';
Nh[i][j]=(m*(i-1)+j);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
Ch[i][j]=Nh[i][j]+n*m;
if(K[i][j]>0)ins(Nh[i][j],Ch[i][j],K[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<=d||j<=d||i>=n-d+1||j>=m-d+1){
ins(Ch[i][j],ed,999999999);
}
}
}
answer=0;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
if(s[j]=='L'){
answer++;ins(st,Nh[i][j],1);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int n1,n2,n3,n4;
n1=max(i-d,1);n2=min(i+d,n);
n3=max(j-d,1);n4=min(j+d,m);
for(int x=n1;x<=n2;x++){
for(int y=n3;y<=n4;y++){
if(pd(i,j,x,y)<=d){
if(x!=i||y!=j){
ins(Ch[i][j],Nh[x][y],999999999);
}
}
}
}
}
}
ans=0;
while(bt()==true){
ans+=findflow(st,999999999);
}
printf("%d\n",answer-ans);
return 0;
}
1.树——树状数组
2.树——线段树
(1). 维护只增数组
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{
int l,r,lc,rc,c;
}tr[510000];
int trlen,n,l,len,t;
void bt(int l,int r){
trlen++;int now=trlen;
tr[now].l=l;tr[now].r=r;tr[now].c=0;
tr[now].lc=tr[now].rc=-1;
if(l<r){
int mid=(l+r)/2;
tr[now].lc=trlen+1;bt(l,mid);
tr[now].rc=trlen+1;bt(mid+1,r);
}
}
void change(int now,int p,long long c){
if(tr[now].l==tr[now].r){tr[now].c=c;return ;}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(p<=mid)change(lc,p,c);
else change(rc,p,c);
tr[now].c=max(tr[lc].c,tr[rc].c);
}
int findmax(int now,int l,int r){
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(mid+1<=l)return findmax(rc,l,r);
else if(r<=mid)return findmax(lc,l,r);
else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}
int main(){
scanf("%d%d",&n,&l);
trlen=len=t=0;bt(1,210000);
char s[10];long long x;
for(int i=1;i<=n;i++){
scanf("%s%d",s,&x);
if(s[0]=='A')change(1,++len,(x+t)%l);
else{
t=findmax(1,len-x+1,len);
printf("%d\n",t);
}
}
}
(2). 维护定量数组
(3). Lazy维护
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{
int l,r,lc,rc;
long long c,lazy;
}tr[510000];
int trlen,n,m,len;
long long a[210000];
void bt(int l,int r){
trlen++;int now=trlen;
tr[now].l=l;tr[now].r=r;
tr[now].c=0;tr[now].lazy=0;
tr[now].lc=tr[now].rc=-1;
if(l==r)tr[now].c=a[l];
else{
int mid=(l+r)/2;
tr[now].lc=trlen+1;bt(l,mid);
tr[now].rc=trlen+1;bt(mid+1,r);
tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
}
}
void change(int now,int x,int y,long long c){
tr[now].c+=(y-x+1)*c;
if(tr[now].l==x&&tr[now].r==y){
tr[now].lazy+=c;return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(y<=mid)change(lc,x,y,c);
else if(x>=mid+1)change(rc,x,y,c);
else{
change(lc,x,mid,c);
change(rc,mid+1,y,c);
}
}
long long findsum(int now,int l,int r){
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(tr[now].lazy!=0){
tr[lc].c+=tr[now].lazy*(tr[lc].r-tr[lc].l+1);
tr[rc].c+=tr[now].lazy*(tr[rc].r-tr[rc].l+1);
tr[lc].lazy+=tr[now].lazy;
tr[rc].lazy+=tr[now].lazy;
tr[now].lazy=0;
}
if(l>=mid+1)return findsum(rc,l,r);
else if(r<=mid)return findsum(lc,l,r);
else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
trlen=0;bt(1,n);
scanf("%d",&m);
int s,x,y;long long z;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&s,&x,&y);
if(s==1){
scanf("%lld",&z);
change(1,x,y,z);
}
else{
printf("%lld\n",findsum(1,x,y));
}
}
}
3.树——伸展树
(1).
4.树——最小生成树
(1). K算法
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,fa[11000],len,maxx,fx,fy,ans;
int findfa(int x){
if(fa[x]!=x)fa[x]=findfa(fa[x]);
return fa[x];
}
struct edge{
int x,y,d;
}e[11000];
int cmp(const void *xx,const void *yy){
edge n1=*(edge *)xx;
edge n2=*(edge *)yy;
return n1.d-n2.d;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
qsort(e+1,m,sizeof(edge),cmp);
for(int i=1;i<=n;i++)fa[i]=i;
ans=0;
for(int i=1;i<=m;i++){
fx=findfa(e[i].x);fy=findfa(e[i].y);
if(fx!=fy){
fa[fx]=fy;
ans++;
if(ans==n-1){
maxx=e[i].d;
break;
}
}
}
printf("%d %d\n",ans,maxx);
}
1.数论——快速幂
(1). gcd
(2).exgcd
(3). 矩阵乘法
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,mod=1000000007;
struct node{
long long a[4][4];
node(){
memset(a,0,sizeof(a));
}
};
node chengfa(node a,node b) {
node c;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
for(int k=1;k<=3;k++){
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
}
}
}
return c;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
node ans,A;
ans.a[1][1]=1;ans.a[2][1]=1;ans.a[3][1]=1;
A.a[1][1]=0;A.a[1][2]=0;A.a[1][3]=1;
A.a[2][1]=1;A.a[2][2]=0;A.a[2][3]=0;
A.a[3][1]=0;A.a[3][2]=1;A.a[3][3]=1;
while(n>0){
if(n%2==1)ans=chengfa(ans,A);
A=chengfa(A,A);
n/=2;
}
printf("%d\n",ans.a[3][3]%mod);
}
}
1.搜索——Dfs
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int s[21][21][21];
bool v[21][21][21];
int a1,b1,c1;
int dfs(int a,int b,int c){
int ans=0;
if(v[a][b][c]==true){
return s[a][b][c];
}
else if(a<=0||b<=0||c<=0)return 1;
else if(a<b&&b<c)ans=dfs(a,b,c-1)+dfs(a,b-1,c-1)-dfs(a,b-1,c);
else ans=dfs(a-1,b,c)+dfs(a-1,b-1,c)+dfs(a-1,b,c-1)-dfs(a-1,b-1,c-1);
v[a][b][c]=true;
s[a][b][c]=ans;
return ans;
}
int main(){
while(scanf("%d%d%d",&a1,&b1,&c1)!=EOF){
if(a1==-1&&b1==-1&&c1==-1)return 0;
else if(a1<=0||b1<=0||c1<=0)printf("w(%d, %d, %d) = 1\n",a1,b1,c1);
else if(a1>20||b1>20||c1>20) printf("w(%d, %d, %d) = %d\n",a1,b1,c1,dfs(20,20,20));
else printf("w(%d, %d, %d) = %d\n",a1,b1,c1,dfs(a1,b1,c1));
}
return 0;
}
(2). 复杂
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int X,Y,K;
double dfs(double x,double y,int k){
double ans=999999999.0,sum;
if(k==1){
return max(x,y)/min(x,y);
}
else{
for(int i=1;i<k;i++){
sum=0.0;
sum=max(sum,dfs((x/k)*i,y,i));
sum=max(sum,dfs(x-((x/k)*i),y,k-i));
ans=min(sum,ans);
sum=0.0;
sum=max(sum,dfs(x,(y/k)*i,i));
sum=max(sum,dfs(x,(y-(y/k)*i),k-i));
ans=min(sum,ans);
}
}
return ans;
}
int main(){
scanf("%d%d%d",&X,&Y,&K);
printf("%.6lf",dfs(X,Y,K));
}
1.DP——一维
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n;double k,c,w,ans;
struct ek{
int k;double c;
}e[110000];
int main(){
scanf("%d%lf%lf%lf",&n,&k,&c,&w);
for(int i=1;i<=n;i++)scanf("%d%lf",&e[i].k,&e[i].c);
ans=0.0;
for(int i=n;i>=1;i--){
if(e[i].k==1){
ans=max(ans,(ans*(1-k/100.0)+e[i].c*w));
}
else{
ans=max(ans,(ans*(1+c/100.0)-e[i].c*w));
}
}
printf("%.2lf\n",ans);
return 0;
}
(2). 复杂
2.DP——二维
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
long long f[5100][5100],n,r,x,y,z,ans=0;
int main(){
scanf("%lld%lld",&n,&r);
memset(f,0,sizeof(f));
if(r==0){
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&x,&y,&z);
f[x+1][y+1]=z;
}
for(int i=1;i<=5001;i++){
for(int j=1;j<=5001;j++)f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
for(int i=r;i<=5001;i++){
for(int j=r;j<=5001;j++){
ans=max(ans,f[i][j]-f[i-r][j]-f[i][j-r]+f[i-r][j-r]);
}
}
printf("%lld\n",ans);
}
(2)复杂
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
long long f[5100][5100],n,r,x,y,z,ans=0;
int main(){
scanf("%lld%lld",&n,&r);
memset(f,0,sizeof(f));
if(r==0){
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&x,&y,&z);
f[x+1][y+1]=z;
}
for(int i=1;i<=5001;i++){
for(int j=1;j<=5001;j++)f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
for(int i=r;i<=5001;i++){
for(int j=r;j<=5001;j++){
ans=max(ans,f[i][j]-f[i-r][j]-f[i][j-r]+f[i-r][j-r]);
}
}
printf("%lld\n",ans);
}
Doc文裆在完善中