个人模板
个人模板
算法
【模板】快速幂
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int a,b,p;
int pow(int a,int b,int p)
{
int ans=1%p;
for(;b;b>>=1){
if(b&1) ans=(long long)ans*a%p;
a=(long long)a*a%p;
}
return ans;
}
int main()
{
scanf("%d%d%d",&a,&b,&p);
printf("%d^%d mod %d=%d\n",a,b,p,pow(a,b,p));
return 0;
}
【模板】二分查找
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 1000005
using namespace std;
int n,m,a[N],q;
int bsearch_precusor(int x)//x或x的后继的下标,不存在大于等于x的数返回n+1
{
int l=1,r=n+1;
while(l<r){
int mid=(l+r)>>1;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
return l;
}
int bsearch_succcessor(int x)//x或x的前驱的下标,不存在小于等于x的数返回0
{
int l=0,r=n;
while(l<r){
int mid=(l+r+1)>>1;
if(a[mid]<=x) l=mid;
else r=mid-1;
}
return l;
}
int bsearch_itself(int x)//x自身的下标,不存在x返回-1
{
int l=1,r=n;
while(l<r){
int mid=(l+r)>>1;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
return (a[l]==x)?l:-1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",a+i);
for(int i=1;i<=m;++i){
scanf("%d",&q);
printf("%d ",bsearch_itself(q));
}
return 0;
}
附:C++ STL中的lower_bound()
与upper_bound()
分别用于查找“x或x的前驱”与“x的前驱”,返回值为指向该元素的指针。
【模板】实数域二分
double l,r,eps=1e-5;
//方法一
while(l+eps<r){
double mid=(l+r)/2;
if(calc(mid)) r=mid;
else l=mid;
}
//方法二
for(int i=0;i<=100;i++){
double mid=(l+r)/2;
if(calc(mid)) r=mid;
else l=mid;
}
【模板】ST表
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100005
using namespace std;
int n,m,a[N],lg[N],f[N][20];//lg[i]=log_2(n)+1
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void ST_prework()
{
for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
for(int i=1;i<=n;i++) f[i][0]=a[i];
int t=lg[n];//t=ceil(log_2(n))
for(int j=1;j<t;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
int ST_query(int l,int r)
{
int k=lg[r-l+1]-1;//k=floor(log_2(r-l+1))
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
ST_prework();
for(int i=1,l,r;i<=m;i++)
l=read(),r=read(),printf("%d\n",ST_query(l,r));
return 0;
}
【模板】单调队列
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,a[1000005],k;
int q[1000005],l,r;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
//min
l=1,r=0;
for(int i=1;i<=n;i++)
{
while(l<=r && q[l]<=i-k) l++;
while(l<=r && a[q[r]]>=a[i]) r--;
q[++r]=i;
if(i>=k) printf("%d ",a[q[l]]);
}
puts("");
//max
l=1,r=0;
for(int i=1;i<=n;i++)
{
while(l<=r && q[l]<=i-k) l++;
while(l<=r && a[q[r]]<=a[i]) r--;
q[++r]=i;
if(i>=k) printf("%d ",a[q[l]]);
}
puts("");
exit(0);
}
【模板】单调栈
【模板】字符串自然溢出哈希
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
int n,ans;
char str[15005];
const ull P=131;
ull a[10005];
ull Hash(char* str)
{
ull ans=0;
for(int i=0;i<strlen(str);++i)
ans=ans*P+(ull)str[i];
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",str),a[i]=Hash(str);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
if(a[i]!=a[i-1])
ans++;
printf("%d\n",ans);
return 0;
}
【模板】整数挂链法哈希
#include<bits/stdc++.h>
#define P 1000003
#define N 1000005
using namespace std;
long long a[N],val[N],cnt[N];
long long f(long long key)
{
return key%P;
}
void get_hash(long long key)
{
int buc=f(abs(key));
while(val[buc]!=key&&val[buc])
buc=(buc+1)%N;
val[buc]=key;cnt[buc]++;
}
long long check(long long key)
{
int buc=f(abs(key));
while(val[buc]!=key&&val[buc])
buc=(buc+1)%N;
if(val[buc]==key)
return cnt[buc];
}
int main()
{
long long n,c,ans=0;
scanf("%lld%lld",&n,&c);
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
get_hash(a[i]);
}
for(int i=0;i<n;i++)
ans+=check(a[i]-c);
printf("%lld",ans);
return 0;
}
【模板】KMP
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 1000005
using namespace std;
int n,m,Next[N],f[N];
char a[N],b[N];
void calc_Next()
{
Next[1]=0;
for(int i=2,j=0;i<=n;i++)
{
while(j>0 && a[i]!=a[j+1]) j=Next[j];
if(a[i]==a[j+1]) j++;
Next[i]=j;
}
}
void calc_f()
{
for(int i=1,j=0;i<=m;i++)
{
while(j>0 && (j==n || b[i]!=a[j+1])) j=Next[j];
if(b[i]==a[j+1]) j++;
f[i]=j;
}
}
int main()
{
scanf("%s%s",b+1,a+1);
n=strlen(a+1),m=strlen(b+1);
calc_Next();
calc_f();
for(int i=1;i<=m;i++)
if(f[i]==n)
printf("%d\n",i-n+1);
for(int i=1;i<=n;i++)
printf("%d ",Next[i]);
return 0;
}
数据结构
【模板】Trie
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 500005
using namespace std;
int n,m;
int trie[N][26],end[N],vis[N],tot=1;
const string ok="OK",wrong="WRONG",repeat="REPEAT";
void insert(char str[])
{
int len=strlen(str),p=1;
for(int i=0;i<len;i++)
{
int ch=str[i]-'a';
if(trie[p][ch]==0) trie[p][ch]=++tot;
p=trie[p][ch];
}
end[p]=1;
}
string find(char str[])
{
int len=strlen(str),p=1;
for(int i=0;i<len;i++)
{
p=trie[p][str[i]-'a'];
if(!p) return wrong;
}
if(end[p])
if(vis[p])
return repeat;
else
{
vis[p]=1;
return ok;
}
}
int main()
{
scanf("%d",&n);
char t[55];
for(int i=1;i<=n;i++)
scanf("%s",t),insert(t);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%s",t),puts(find(t));
return 0;
}
【模板】树状数组 1
#include<bits/stdc++.h>
using namespace std;
int n,m,tree[1000005],s[1000005];
int t;
inline void add(int x,int y)
{
for(;x<=n;x+=x&-x)
tree[x]+=y;
}
inline int ask(int x)
{
int ans=0;
for(;x;x-=x&-x)
ans+=tree[x];
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1,w;i<=n;i++)
{
cin>>s[i];add(i,s[i]);
}
for(int i=1,a,x,y;i<=m;i++)
{
cin>>a>>x>>y;
if(a==1) add(x,y);
if(a==2) cout<<ask(y)-ask(x-1)<<endl;
}
return 0;
}
【模板】树状数组 2
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
long long a[500005],tr[500005],n,m;
inline void add(long long x,long long k)
{
for(;x<=n;x+=x&-x)
tr[x]+=k;
}
inline long long ask(long long x)
{
int ans=0;
for(;x;x-=x&-x)
ans+=tr[x];
return ans;
}
int main()
{
long long t,x,y,k;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
add(i,a[i]-a[i-1]);
}
while(m--)
{
cin>>t;
if(t==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
add(x,k),add(y+1,-k);
}
else
{
scanf("%lld",&x);
printf("%lld\n",ask(x));
}
}
return 0;
}
【模板】树状数组 3
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define N 100005
using namespace std;
long long tree[N],tree2[N],a[N],n,m;
inline void add(long long x,long long k)
{
for(long long x0=x;x<=n;x+=x&-x)
tree[x]+=k,tree2[x]+=k*x0;
}
inline long long ask(long long x)
{
long long ans=0;
for(int x1=x+1;x;x-=x&-x)
ans+=x1*tree[x]-tree2[x];
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
char c;
for(long long i=1;i<=n;i++)
{
cin>>a[i],add(i,a[i]-a[i-1]);
}
for(long long i=1,t,l,r,k;i<=m;i++)
{
cin>>c>>l>>r;
if(c=='C') cin>>k,add(l,k),add(r+1,-k);
if(c=='Q') cout<<ask(r)-ask(l-1)<<endl;
}
return 0;
}
【模板】树状数组 RMQ
#include<iostream>
#include<algorithm>
#include<cstring>
#include<ctime>
#define N 1000005
#define lowbit(x) (x&-x)
//#define int unsigned long long
using namespace std;
int n,m,c,a[N],cnttimes,trmax[N],trmin[N];
string op;
inline void add(int x,int k)
{
for(;x<=n;x+=lowbit(x))
trmax[x]=max(trmax[x],k),trmin[x]=min(trmin[x],k);
}
inline int askmax(int l,int r)
{
if(l<r){
if(l<(r-lowbit(r))) return max(trmax[r],askmax(l,r-lowbit(r)));
else return max(askmax(l,r-1),a[r]);
}
else
return a[l];
}
inline int askmin(int l,int r)
{
if(l<r)
if(r-lowbit(r)>l) return min(trmin[r],askmin(l,r-lowbit(r)));
else return min(askmin(l,r-1),a[r]);
return a[l];
}
int main()
{
memset(trmin,0x3f3f3f3f,sizeof(trmin));
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i],add(i,a[i]);
for(int i=1,l,r;i<=m;i++)
{
cnttimes=0;
cin>>op>>l>>r;
if(op=="max") cout<<askmax(l,r)<<endl;
if(op=="min") cout<<askmin(l,r)<<endl;
}
return 0;
}
【模板】线段树 1(区间修改,区间查询)
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100005
using namespace std;
struct SegmentTree{
int l,r;
long long dat,add;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define dat(x) tree[x].dat
#define add(x) tree[x].add
}tree[N<<2];
int n,m,a[N];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void build(int p,int l,int r){
l(p)=l,r(p)=r;
if(l==r) {dat(p)=a[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
void spread(int p)
{
if(add(p)){
dat(p<<1)+=add(p)*(r(p<<1)-l(p<<1)+1);
dat(p<<1|1)+=add(p)*(r(p<<1|1)-l(p<<1|1)+1);
add(p<<1)+=add(p);
add(p<<1|1)+=add(p);
add(p)=0;
}
}
void change(int p,int l,int r,int d){
if(l<=l(p) && r>=r(p)){
dat(p)+=(long long)d*(r(p)-l(p)+1);
add(p)+=d;
return;
}
spread(p);
int mid=(l(p)+r(p))>>1;
if(l<=mid) change(p<<1,l,r,d);
if(r>mid) change(p<<1|1,l,r,d);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
long long ask(int p,int l,int r){
if(l<=l(p) && r>=r(p)) return dat(p);
spread(p);
int mid=(l(p)+r(p))>>1;
long long val=0;
if(l<=mid) val+=ask(p<<1,l,r);
if(r>mid) val+=ask(p<<1|1,l,r);
return val;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
build(1,1,n);
while(m--)
{
int op,x,y,d;
op=read(),x=read(),y=read();
if(op==1)
d=read(),change(1,x,y,d);
if(op==2)
printf("%lld\n",ask(1,x,y));
}
return 0;
}
【模板】线段树 2(区间加,区间乘,区间查询)
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100005
using namespace std;
struct SegmentTree{
int l,r;
long long dat,add,mul;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define dat(x) tree[x].dat
#define add(x) tree[x].add
#define mul(x) tree[x].mul
}tree[N<<2];
int n,m,P,a[N];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void build(int p,int l,int r){
l(p)=l,r(p)=r,add(p)=0,mul(p)=1;
if(l==r) {dat(p)=a[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
dat(p)=(dat(p<<1)+dat(p<<1|1))%P;
}
void spread(int p){
if(add(p)==0&&mul(p)==1) return;
dat(p<<1)=(dat(p<<1)*mul(p)+add(p)*(r(p<<1)-l(p<<1)+1))%P;
dat(p<<1|1)=(dat(p<<1|1)*mul(p)+add(p)*(r(p<<1|1)-l(p<<1|1)+1))%P;
add(p<<1)=(add(p<<1)*mul(p)+add(p))%P;
add(p<<1|1)=(add(p<<1|1)*mul(p)+add(p))%P;
mul(p<<1)=(mul(p<<1)*mul(p))%P;
mul(p<<1|1)=(mul(p<<1|1)*mul(p))%P;
add(p)=0;
mul(p)=1;
}
void changeadd(int p,int l,int r,int d){
if(l<=l(p) && r>=r(p)){
dat(p)=(dat(p)+(long long)d*(r(p)-l(p)+1))%P;
add(p)=(add(p)+(long long)d)%P;
return;
}
spread(p);
int mid=(l(p)+r(p))>>1;
if(l<=mid) changeadd(p<<1,l,r,d);
if(r>mid) changeadd(p<<1|1,l,r,d);
dat(p)=(dat(p<<1)+dat(p<<1|1))%P;
}
void changemul(int p,int l,int r,int d){
if(l<=l(p) && r>=r(p)){
dat(p)=(dat(p)*(long long)d)%P;
add(p)=(add(p)*(long long)d)%P;
mul(p)=(mul(p)*(long long)d)%P;
return;
}
spread(p);
int mid=(l(p)+r(p))>>1;
if(l<=mid) changemul(p<<1,l,r,d);
if(r>mid) changemul(p<<1|1,l,r,d);
dat(p)=(dat(p<<1)+dat(p<<1|1))%P;
}
long long ask(int p,int l,int r){
if(l<=l(p) && r>=r(p)) return dat(p);
spread(p);
int mid=(l(p)+r(p))>>1;
long long val=0;
if(l<=mid) val=(val+ask(p<<1,l,r))%P;
if(r>mid) val=(val+ask(p<<1|1,l,r))%P;
return val%P;
}
int main()
{
n=read(),m=read(),P=read();
for(int i=1;i<=n;i++)
a[i]=read();
build(1,1,n);
while(m--)
{
int op,x,y,d;
op=read(),x=read(),y=read();
if(op==1)
d=read(),changemul(1,x,y,d);
if(op==2)
d=read(),changeadd(1,x,y,d);
if(op==3)
printf("%lld\n",ask(1,x,y)%P);
}
return 0;
}
【模板】线段树(单点修改,区间查询)
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100005
using namespace std;
struct SegmentTree{
int l,r;
int dat;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define dat(x) tree[x].dat
}tree[N<<2];
int n,m,a[N];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void build(int p,int l,int r){
l(p)=l,r(p)=r;
if(l==r) {dat(p)=a[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
void change(int p,int x,int v){
if(l(p)==r(p)) {dat(p)+=v;return;}
int mid=(l(p)+r(p))>>1;
if(x<=mid) change(p<<1,x,v);
else change(p<<1|1,x,v);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
int ask(int p,int l,int r){
if(l<=l(p)&&r>=r(p)) return dat(p);
int mid=(l(p)+r(p))>>1;
int val=0;
if(l<=mid) val+=ask(p<<1,l,r);
if(r>mid) val+=ask(p<<1|1,l,r);
return val;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op=read(),a,b;
if(op==1) a=read(),b=read(),change(1,a,b);
if(op==2) a=read(),b=read(),printf("%d\n",ask(1,1,b)-ask(1,1,a-1));
}
return 0;
}
【模板】线段树(区间修改,单点查询)
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100005
using namespace std;
struct SegmentTree{
int l,r;
int dat;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define dat(x) tree[x].dat
}tree[N<<2];
int n,m,a[N];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void build(int p,int l,int r){
l(p)=l,r(p)=r;
if(l==r) {dat(p)=a[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
void change(int p,int x,int v){
if(l(p)==r(p)) {dat(p)+=v;return;}
int mid=(l(p)+r(p))>>1;
if(x<=mid) change(p<<1,x,v);
else change(p<<1|1,x,v);
dat(p)=dat(p<<1)+dat(p<<1|1);
}
int ask(int p,int l,int r){
if(l<=l(p)&&r>=r(p)) return dat(p);
int mid=(l(p)+r(p))>>1;
int val=0;
if(l<=mid) val+=ask(p<<1,l,r);
if(r>mid) val+=ask(p<<1|1,l,r);
return val;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read(),a[i]-=a[i-1];
build(1,1,n+1);
for(int i=1;i<=m;i++)
{
int op=read(),a,b;
if(op==1) a=read(),b=read(),change(1,a,1),change(1,b+1,-1);
if(op==2) a=read(),printf("%d\n",ask(1,1,a));
}
return 0;
}
图论
【模板】Floyd最小环
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
#define int long long
#define inf 0x3f3f3f3f
using namespace std;
int n,m,a[128][128],dis[128][128],pre[128][128],ans=inf;
vector<int>P;
void get_path(int x,int y)//记录路径的操作可以递归解决
{
if(!pre[x][y])
return ;
get_path(x,pre[x][y]);
P.push_back(pre[x][y]);
get_path(pre[x][y],y);
return ;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j) dis[i][j]=a[i][j]=inf;
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
a[u][v]=a[v][u]=min(a[u][v],w);
dis[v][u]=dis[u][v]=min(dis[u][v],w);
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++)
if(dis[i][j]+a[i][k]+a[k][j]<ans){
ans=dis[i][j]+a[i][k]+a[k][j];
P.clear();
P.push_back(i);
get_path(i,j);
P.push_back(j);
P.push_back(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[j][i]=dis[i][j]=dis[i][k]+dis[k][j];
pre[j][i]=pre[i][j]=k;
}
}
}
if(ans==inf){
printf("No solution.\n");
return 0;
}
for(int i=0;i<P.size();i++)
printf("%lld ",P[i]);
return 0;
}
【模板】Dijsktra
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define N 100005
#define M 1000005
#define inf 2147483647
using namespace std;
int n,m,s,t,head[N],dis[N],tot=0;
bool vis[N];
struct edge{
int nxt,to,w;
}e[M];
struct node{
int x,d;
bool operator<(const node &A)const
{
return d>A.d;
}
};
priority_queue<node>Q;
inline void addedge(int x,int y,int w)
{
tot++;
e[tot].nxt=head[x];
e[tot].to=y;
e[tot].w=w;
head[x]=tot;
return ;
}
inline void dij()
{
for(int i=1;i<=n;i++) dis[i]=inf;
memset(vis,false,sizeof(vis));
Q.push((node){s,0});
dis[s]=0;
while(!Q.empty())
{
int now=Q.top().x;
Q.pop();
if(vis[now])continue;
vis[now]=true;
for(int i=head[now];i;i=e[i].nxt)
{
int to=e[i].to;
if(dis[to]>dis[now]+e[i].w)
{
dis[to]=dis[now]+e[i].w;
Q.push((node){to,dis[to]});
}
}
}
return ;
}
signed main()
{
ios::sync_with_stdio(0);
cin>>n>>m>>s>>t;
for(int i=1,u,v,w;i<=m;i++)
cin>>u>>v>>w,addedge(u,v,w);
dij();
for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}
【模板】SPFA
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define N 10005
#define M 500005
using namespace std;
struct Edge{
int nxt,to,w;
}e[M];
queue<int>q;
bool v[N];
int n,m,s;
int tot,head[N],d[N];
inline void addedge(int x,int y,int w)
{
e[++tot]=(Edge){head[x],y,w};
head[x]=tot;
}
inline void SPFA()
{
for(int i=1;i<=n;i++) d[i]=2147483647;
memset(v,false,sizeof v);
d[s]=0,v[s]=1;
q.push(s);
while(q.size())
{
int x=q.front();q.pop();
v[x]=0;
for(int i=head[x],y,z;i;i=e[i].nxt)
{
y=e[i].to,z=e[i].w;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(!v[y])
q.push(y),v[y]=1;
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>s;
for(int i=1,x,y,w;i<=m;i++)
cin>>x>>y>>w,addedge(x,y,w);
SPFA();
for(int i=1;i<=n;i++)
cout<<d[i]<<" ";
cout<<endl;
return 0;
}
【模板】倍增LCA
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 500005
using namespace std;
int cnt,head[N];
struct Edge{
int nxt,to;
}e[N<<1];
int lg[N],de[N],anc[N][25];//lg[i]=log_2(i)+1
int n,m,s;
void addedge(int x,int y)
{
e[++cnt].nxt=head[x],e[cnt].to=y,head[x]=cnt;
}
void dfs(int x,int fa)
{
de[x]=de[fa]+1;
anc[x][0]=fa;
for(int i=1;i<=lg[de[x]];++i)
anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa)
dfs(e[i].to,x);
}
int LCA(int x,int y)
{
if(de[x]<de[y]) swap(x,y);
while(de[x]>de[y])
x=anc[x][lg[de[x]-de[y]]-1];
if(x==y) return x;
for(int i=lg[de[x]]-1;i>=0;--i)
if(anc[x][i]!=anc[y][i])
x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1,x,y;i<n;i++)
scanf("%d%d",&x,&y),addedge(x,y),addedge(y,x);
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dfs(s,0);
for(int i=1,x,y;i<=m;i++)
scanf("%d%d",&x,&y),printf("%d\n",LCA(x,y));
return 0;
}
【模板】Kruskal
#include<bits/stdc++.h>
using namespace std;
int fa[305];
struct edge
{
int x,y,z;
bool operator<(const edge&tmp)
{
return z<tmp.z;
}
}e[100005];
int getfa(int x)
{
return (fa[x]==x ? x : fa[x]=getfa(fa[x]));
}
int main()
{
int n,m,ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
cin>>e[i].x>>e[i].y>>e[i].z;
sort(e,e+m);
for(int i=1,x,y;i<=m;i++)
{
x=getfa(e[i].x);y=getfa(e[i].y);
if(x==y) continue;
fa[x]=y;
ans+=e[i].z;
}
cout<<ans;
return 0;
}
【模板】割点
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#define N 20005
#define M 100005
using namespace std;
struct Edge{
int nxt,to;
}e[M<<1];
int n,m,cnt,head[N];
int root,tot,cut[N],dfn[N],low[N],ans;
void addedge(int x,int y)
{
++cnt;
e[cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void tarjan(int u)
{
int flag=0;
dfn[u]=low[u]=++tot;
for (int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
flag++;
if(u!=root||flag>1) cut[u]=1;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1,x,y;i<=m;i++)
cin>>x>>y,addedge(x,y),addedge(y,x);
for(int i=1;i<=n;i++)
if(!dfn[i])
root=i,tarjan(i);
for(int i=1;i<=n;i++)
if(cut[i])
ans++;
cout<<ans<<endl;
for(int i=1;i<=n;i++)
if(cut[i])
cout<<i<<" ";
exit(0);
}
【模板】割边
【模板】Tarjan 强连通分量缩点 + DAG上dp
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#define N 10005
#define M 100005
using namespace std;
struct Edge{
int nxt,to;
}e[M];
int n,m,x[M],y[M],cnt,head[N],indgr[N],f[N],ans;
int tot,dfn[N],low[N],top,stk[N],a[N],col,co[N],num[N];
void addedge(int x,int y)
{
++cnt;
e[cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void tarjan(int u)
{
low[u]=dfn[u]=++tot;
stk[++top]=u;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!dfn[v])
tarjan(v),low[u]=min(low[u],low[v]);
else if(!co[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
++col;
while(stk[top+1]!=u)
num[col]+=a[stk[top]],co[stk[top]]=col,--top;
}
return;
}
void rebuild()
{
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
cnt=0;
for(int i=1;i<=m;i++)
if(co[x[i]]!=co[y[i]])
addedge(co[x[i]],co[y[i]]);
}
int dfs(int x){
if(f[x]) return f[x];
f[x]=num[x];
int res=0;
for(int i=head[x];i;i=e[i].nxt)
res=max(dfs(e[i].to),res);
f[x]+=res;
return res;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
cin>>x[i]>>y[i],addedge(x[i],y[i]);
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
rebuild();
for(int i=1;i<=col;i++)
dfs(i),ans=max(ans,f[i]);
cout<<ans;
exit(0);
}
【模板】静态链分治/树上启发式合并
//CF600E Lomsat gelal
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 100005
using namespace std;
struct Edge{
int nxt,to;
}e[N<<1];
int n,tot,head[N],co[N],siz[N];
bool hson[N];
long long ans[N],a[N],maxa,cntans;
inline void addedge(int x,int y)
{
e[++tot]=(Edge){head[x],y};
head[x]=tot;
}
void getsiz(int x,int pre)
{
int maxsiz=0,Hson=0;
siz[x]=1;
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==pre) continue;
getsiz(y,x);
siz[x]+=siz[y];
if(siz[y]>maxsiz)
maxsiz=siz[y],Hson=y;
}
hson[Hson]=Hson?1:0;
}
void getans(int x,int pre,int Hson)
{
a[co[x]]++;
if(a[co[x]]>maxa)
maxa=a[co[x]],cntans=co[x];
else if(a[co[x]]==maxa)
cntans+=co[x];
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==pre||y==Hson) continue;
getans(y,x,Hson);
}
}
void clear(int x,int pre)
{
a[co[x]]--;
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==pre) continue;
clear(y,x);
}
}
void solve(int x,int pre)
{
int Hson=0;
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==pre) continue;
if(!hson[y])
{
solve(y,x);
clear(y,x),maxa=cntans=0;
}
else Hson=y;
}
if(Hson)
solve(Hson,x);
getans(x,pre,Hson);
ans[x]=cntans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",co+i);
for(int i=1,x,y;i<=n-1;i++)
scanf("%d%d",&x,&y),addedge(x,y),addedge(y,x);
getsiz(1,0);
solve(1,0);
for(int i=1;i<=n;i++)
printf("%lld ",ans[i]);
return 0;
}
【模板】二分图染色
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#define N 10005
using namespace std;
vector<int>g[N];
int n,m,vis[N],col[N],ans=1;
bool dfs(int u)
{
vis[u]=1;
for(int i=0,v;i<g[u].size();i++)
{
v=g[u][i];
if(col[u]==col[v])
return false;
if(col[v]==-1)
{
col[v]=!col[u];
if(!dfs(v))
return false;
}
}
return true;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1,u,v;i<=m;i++)
cin>>u>>v,g[u].push_back(v);
for(int i=1;i<=n;i++)
{
memset(col,-1,sizeof(col)),col[i]=0;
if(!vis[i])
ans+=dfs(i);
}
if(ans) printf("%d\n",ans);
else printf("Impossible\n");
return 0;
}
【模板】二分图最大匹配
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 1005
#define M 50005
using namespace std;
struct edge{
int nxt,to;
}e[M<<1];
int n,m,e0,tot,head[N],visit[N],match[N],ans;
void addedge(int x,int y)
{
e[++tot]=(edge){head[x],y};
head[x]=tot;
}
bool dfs(int x)
{
for(int i=head[x],y;i;i=e[i].nxt)
if(!visit[y=e[i].to])
{
visit[y]=1;
if(!match[y]||dfs(match[y]))
{
match[y]=x;
return true;
}
}
return false;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m>>e0;
for(int i=1,u,v;i<=e0;i++)
cin>>u>>v,addedge(u,v+n);
for(int i=1;i<=n;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i)) ans++;
}
cout<<ans<<endl;
exit(0);
}
【模板】网络流 Edmond Karp
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define N 205
#define M 5005
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
struct Edge{
int nxt,to,w;
}e[M<<1];
int n,m,s,t,tot=1,head[N],flag[N][N],vis[N],pre[N],incf[N],maxflow;
void addedge(int x,int y,int z)
{
e[++tot]=(Edge){head[x],y,z},head[x]=tot;
e[++tot]=(Edge){head[y],x,0},head[y]=tot;
}
bool bfs()
{
memset(vis,0,sizeof vis);
queue<int>q;
q.push(s);vis[s]=1;
incf[s]=inf;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].nxt)
if(e[i].w)
{
int y=e[i].to;
if(vis[y]) continue;
incf[y]=min(incf[x],e[i].w);
pre[y]=i;
q.push(y);vis[y]=1;
if(y==t) return true;
}
}
return false;
}
void update()
{
int x=t;
while(x!=s)
{
int i=pre[x];
e[i].w-=incf[t];
e[i^1].w+=incf[t];
x=e[i^1].to;
}
maxflow+=incf[t];
}
signed main()
{
scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
for(int i=1,x,y,z;i<=m;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
if(!flag[x][y])
addedge(x,y,z),flag[x][y]=tot-1;
else
e[flag[x][y]].w+=z;
}
while(bfs()) update();
printf("%lld\n",maxflow);
return 0;
}
【模板】网络流 Dinic
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define N 205
#define M 5005
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
struct Edge{
int nxt,to,w;
}e[M<<1];
queue<int>q;
int tot=1,head[N],flag[N][N],d[N],now[N];
int n,m,s,t;
int maxflow;
void addedge(int x,int y,int z)
{
e[++tot]=(Edge){head[x],y,z},head[x]=tot;
e[++tot]=(Edge){head[y],x,0},head[y]=tot;
}
bool bfs()
{
memset(d,0,sizeof 0);
while(!q.empty()) q.pop();
q.push(s);
d[s]=1,now[s]=head[s];
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(e[i].w && !d[y])
{
q.push(y);
d[y]=d[x]+1;
now[y]=head[y];
if(y==t) return true;
}
}
}
return false;
}
int dinic(int x,int flow)
{
if(x==t) return flow;
int rest=flow;
for(int i=head[x],y,k;i&&rest;i=e[i].nxt)
{
y=e[i].to;
if(e[i].w && d[y]==d[x]+1)
{
k=dinic(y,min(rest,e[i].w));
if(!k) d[y]=0;
e[i].w-=k;
e[i^1].w+=k;
rest-=k;
}
}
return flow-rest;
}
signed main()
{
scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
for(int i=1,x,y,z;i<=m;i++)
scanf("%lld%lld%lld",&x,&y,&z),addedge(x,y,z);
int flow=0;
while(bfs())
while(flow=dinic(s,inf))
maxflow+=flow;
printf("%lld\n",maxflow);
return 0;
}