十个板子

1.网络流最大流:dinic

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
const int M = 1e5+10;
/*下面就是著名的dinic算法了*/
template <typename T>
struct FlowGraph{
	/*
	N:点数
	M:边数
	*/
	int s,t,vtot;
	int head[N],etot;
	int dep[N],cur[N];
	struct edge{
		int to,nxt;
		T val;
	} e[M*2];
	void addedge(int x,int y,T f1,T f2){//加边
		e[etot]={x,head[x],f1}; head[x]=etot++;
		e[etot]={y,head[y],f2}; head[y].etot++;
	}
	bool bfs(){//宽搜,看看有没有增广
		for(int i=1;i<=vtot;i++){
			dep[i]=0;
			cur[i]=head[i];
		}
		queue<int> q;
		q.push(s);dep[s]=1;
		while(q.size()){
			int x=q.front();
			q.pop();
			for(int i=head[x];i;i=e[i].nxt){
				int to=e[i].to;
				if(e[i].val && !dep[to]){
					dep[to]=dep[x]+1;
					q.push(to);
				}
			}
		}
		if(dep[t]) return true;
		else return false;
	}
	T dfs(int x,T flow){//多路增广
		if(x==t) return flow;
		T out=0;
		for(int i=cur[x];i && flow ;i=cur[x]=e[x].nxt){
			int to=e[i].to;
			if(e[i].val && dep[to]==dep[x]+1){
				T res=dfs(to,min(e[i].val,flow));
				e[i].val-=res;
				e[i^1].val+=res;
				flow-=res;
				out+=res;
			}
		}
		if(out==0) dep[x]=0;
		return out;
	}
	T dinic(){
		T ans=0;
		while(bfs()) ans+=dfs(s,numeric_limits<T>::max());
		return ans;
	}
	void init(int s_,int t_,int vtot_){//初始化
		s=_s;
		t=_t;
		vtot=vtot_;
		etot=0;
		for(int i=1;i<=vtot;i++) head[i]=-1;
	}
};
FlowGraph<int> G;//定义一个网络流

2.费用流(EK算法)

#include <bits/stdc++.h>
using namespace std;
const int N = 5*1e3+10 ;
const int M = 1e5+10 ;
const int inf = 0x3f3f3f3f;
int n,m;
template <typename T>
struct ValueGraph
{
	int s,t,vtot;
	int head[N],etot,pre[N];//pre:记录这个点的上一条边是什么
	bool vis[N];
	T dis[N],flow,cost;
	struct edge{
		int to;
		int nxt;
		T val,w;//val : 这条边的流量
				 //w : 这条边要用的费用
	}e[M];
	void addedge(int x,int y,T z,T w){//w:这,T 条边要用的费用
									  //z:这条边的流量
		e[etot]=(edge){y,head[x],z,w};  head[x]=etot++;
		e[etot]=(edge){x,head[y],0,-w}; head[y]=etot++;
	}
	bool spfa(){
		
		for(int i=1;i<=vtot;i++)
			dis[i]=inf,vis[i]=false,pre[i]=-1;

		dis[s]=0;
		vis[s]=true;
		queue<int> q;
		q.push(s);
		while(q.size()){
			int x=q.front();q.pop();
			for(int i=head[x];~i/******/;i=e[i].nxt){
				int to=e[i].to;
				if(e[i].val && dis[to] > dis[x]+e[i].w){
					dis[to]=dis[x]+e[i].w;
					pre[to]=i;
					if(!vis[to]){
						vis[to]=1;
						q.push(to);
					}
				}
			}
			vis[x] = false; /*********/
		}
		return dis[t]!=inf;
	}
	void augment(){//增广
		int x=t;
		T f=inf;
		while(~pre[x]){
			f=min(f,e[pre[x]].val);
			x=e[pre[x] ^ 1].to;
		}
		flow += f;
		cost += f*dis[t];
		x = t;
		while(~pre[x]){
			e[pre[x]].val-=f;
			e[pre[x] ^ 1].val+=f;
			x=e[pre[x] ^ 1].to;
		}
	}
	pair<T,T> solve(){
		flow=0;
		cost=0;
		while(spfa()) augment();
		return make_pair(flow,cost);
	}
	void init(int s_,int t_,int vtot_){
		s=s_;
		t=t_;
		for(int i=1;i<=vtot_;i++) head[i]=-1;
		vtot=vtot_;
	}
};
ValueGraph<int> G;
int main(){
	int s,t;
	scanf("%d%d%d%d",&n,&m,&s,&t);
	
	G.init(s,t,n);

	for(int i=1;i<=m;i++){
		int x,y,w,co;
		scanf("%d%d%d%d",&x,&y,&w,&co);
		G.addedge(x,y,w,co);
	}
	int flow,cost;
	pair <int,int> p=G.solve();
	flow=p.first;cost=p.second;
	printf("%d %d\n",flow,cost);
	return 0;
}

3.拓展欧几里得

typedef long long ll ;
ll exgcd(int a,int b,int &x,int &y){
	if(b==0) return a;
	int d=exgcd(b,a%b,x,y);
	int z=x;
	x=y;y=z-(a/b)*y;
	return d;
}

4.SPFA

#include <bits/stdc++.h>
using namespace std;
const int N =1e5+10 ;
const int inf = 0x3f3f3f3f ;
int n,m;
struct node
{
	int to;
	int w;
};
std::vector<node> v[N];
int dis[N],vis[N];
void spfa(int s){
	memset(dis,inf,sizeof(dis));
	queue<int> q;
	q.push(s);dis[s]=0;
	vis[s]=true;
	while(q.size()){
		int x=q.front();q.pop();
		for(auto nxt:v[x]){
			int to=nxt.to;
			int w=nxt.w;
			if(dis[to]>dis[x]+w){
				dis[to]=dis[x]+w;
				if(!vis[to]){
					vis[to]=1;
					q.push(to);
				}
			}
		}
		vis[x]=false;/**********/
	}
}

5.判断负环

#include <bits/stdc++.h>
using namespace std;
const int N =1e5+10 ;
const int inf = 0x3f3f3f3f ;
int n,m;
struct node
{
	int to;
	int w;
};
std::vector<node> v[N];
int dis[N],vis[N],cnt[N];
bool spfa(int s){//返回true就是有负环
	memset(dis,inf,sizeof(dis));
	memset(0,cnt,sizeof(cnt));
	queue<int> q;
	q.push(s);dis[s]=0;
	vis[s]=true;
	cnt[s]=1;
	while(q.size()){
		int x=q.front();q.pop();
		for(auto nxt:v[x]){
			int to=nxt.to;
			int w=nxt.w;
			if(dis[to]>dis[x]+w){
				dis[to]=dis[x]+w;
				if(!vis[to]){
					cnt[to]++;
					if(cnt[to]>=n) return true;
					vis[to]=1;
					q.push(to);
				}
			}
		}
		vis[x]=false;
	}
	return false;
}

6.求 \(\phi (x)\)

#include <bits/stdc++.h>
using namespace std;
//phi(x)的计算式:phi(x)=x * Σ ( 1 - 1/p ) p代表x的所有质因数(相同的只算一次)
ll phi(ll p)
{
	ll ans = p,q = p;
	for(int i = 2; i * i <= q; i ++)
	{
		if(q % i != 0) continue;
		ans = ans / i * (i - 1);
		while(q % i == 0) q /= i;
	}
	if(q != 1) ans = ans / q * (q - 1);
	return ans;
}

7.矩阵快速幂(以斐波那契数列为例)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
ll n;
struct matrix
{
	ll a[5][5];
	matrix(){
		memset(a,0,sizeof(a));
	}
	inline void base()
	{
		a[1][1]=a[2][1]=a[1][2]=1;
	}
	inline void res()
	{
		a[1][1]=a[2][1]=1;
	}
};
matrix operator *(const matrix &x,const matrix &y)
{
	matrix ans;
	for(int k=1;k<=2;k++)
		for(int i=1;i<=2;i++)
			for(int j=1;j<=2;j++)
				ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
	return ans;
}
int main()
{
	cin>>n;
	matrix ans,base;
	ans.res();base.base();
	if(n<=2)
	{
		cout<<1<<endl;
		return 0;
	}
	n-=1;
	while(n)
	{
		if(n%2) ans=ans*base;
		base=base*base;
		n/=2;
	}
	cout<<ans.a[1][1]<<endl;
	return 0;
}

8.FFT,快速傅里叶变换

//FFT
#include <bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
#define RF(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline void read(int &x)
{
	char ch=getchar();
	int s=0,f=1;
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f*-=1;
	for(; isdigit(ch);ch=getchar()) s*=10,s+=ch-'0';
	return s*f;
}
const int N = 1e6+10 ;
const double pi=acos(-1,0);
int n,m;
struct complex{
	double x,y;
	complex (double xx=0,double yy=0){x=xx,y=yy;}
}a[N],b[N];
complex operator +(complex aa,complex bb){return complex(aa.x+bb.x,aa.y+bb.y);}
complex operator -(complex aa,complex bb){return complex(aa.x-bb.x,aa.y+bb.y);}
complex operator *(complex aa,complex bb){return complex(aa.x*bb.x-aa.y*bb.y,aa.y*bb.x+aa.x*bb.y);}
//limit:代表了项数
//x:代表了当前多项式的系数
//type:变换类型
void FFT(int limit,complex *x,int type)
{
	if(limit==1) return ;
	complex a1[limit>>1],a2[limit>>1];
	for(int i=0;i<=limit;i+=2)
		a1[i>>1]=x[i],a2[i>>1|1]=x[i+1];
	FFT(limit>>1,a1,type);
	FFT(limit>>1,a2,type);
	complex wn=complex(cos((2.0*pi/limit)),type*sin(2.0*pi/limit)),w=complex(1,0);
	for(int i=0;i<(limit>>1);i++,w=w*wn)
	{
		a[i]=a1[i]+w*a2[i];
		a[i+(limit>>1)]=a1[i]-w*a2[i];
	}
}
int main()
{
	read(n);
	read(m);
	F(i,1,n) read(a[i].x);
	F(i,1,m) read(b[i].x);
	int limit=1;
	while(limit<=n+m) limit*=2;
	
	return 0;
}

9.树链剖分

const int N = 1e5+10 ;
std::vector<int> v[N];
int dep[N],siz[N],top[N],dfn[N],rev[N],fa[N];
/*
dep[x]:节点x的深度
siz[x]:以x为根子树的大小
top[x]:x所在重链的顶端
dfn[x]:x在线段树序列中对应的编号
rev[x]:线段树序列中的x对应的树上节点
fa[x]:x的爸爸
*/
int cnt;
void dfs1(int x,int f){
	dep[x]=dep[f]+1;
	fa[x]=f;
	siz[1]=1;
	int maxson=0;
	for(auto to:v[x]){
		if(to==f) continue;
		dfs1(to,x);
		siz[x]+=siz[to];
		if(siz[to]>maxson) son[x]=to,maxson=siz[to];
	}
}
void dfs2(int x,int tp){
	top[x]=tp,dfn[x]=++cnt,rev[cnt]=x;
	if(son[x]) dfs2(son[x],tp);
	for(auto to:v[x]){
		if(to==fa[x]) continue;
		if(to==son[x]) continue;
		dfs2(to,to);
	}
}

10.KMP

#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
char s1[N+10],s2[N+10];
int n,m,p[N]; 
int main()
{
	cin>>s1+1;
	cin>>s2+1;
	n=strlen(s1+1);
	m=strlen(s2+1);
	int j;
	j=0;
	for(int i=1;i<m;i++)
	{
		while(j && s2[j+1]!=s2[i+1]) j=p[j];
		if(s2[j+1]==s2[i+1]) j++;
		p[i+1]=j;
	}
	j=0;
	for(int i=0;i<n;i++)
	{
		while(j && s2[j+1]!=s1[i+1]) j=p[j];
		if(s2[j+1]==s1[i+1]) j++;
		if(j==m)
		{
			cout<<i-m+2<<endl;
			j=p[j];
		}
	}
	for(int i=1;i<=m;i++)
		cout<<p[i]<<' ';
}
posted @ 2022-08-26 10:42  羊扬羊  阅读(31)  评论(0)    收藏  举报