十个板子
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]<<' ';
}
本文来自博客园,作者:羊扬羊,转载请注明原文链接:https://www.cnblogs.com/sheepcsy/p/16626795.html

浙公网安备 33010602011771号