个人模板

个人模板

算法

【模板】快速幂

#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;
}
posted @ 2020-11-04 22:43  LZShuing  阅读(166)  评论(1编辑  收藏  举报