上次电脑硬盘坏了,整理几个月的模板顷刻间灰飞烟灭QAQ,所以有必要把一些东西传到博客上。
后缀数组相关
后缀数组
int n,str[maxn],sa[maxn],rk[maxn];
int c[maxn],x[maxn],xa[maxn],y[maxn],m;
void getSa(){
m=255;//
memset(c,0,sizeof(int)*(m+1));
for(int i=1;i<=n;i++) c[x[i]=str[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++) sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k+1;i<=n;i++) y[++p]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
memset(c,0,sizeof(int)*(m+1));
for(int i=1;i<=n;i++) c[x[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i];
memcpy(xa,x,sizeof(int)*(n+1));
x[sa[1]]=1;
p=1;
for(int i=2;i<=n;i++){
x[sa[i]]=(xa[sa[i]]==xa[sa[i-1]] && xa[sa[i]+k]==xa[sa[i-1]+k] ? p:++p);
}
if(p==n)break;
m=p;
}
for(int i=1;i<=n;i++)rk[sa[i]]=i;
}
后缀自动机
// 小写字母版
const int maxn=1e6+5;
struct state{
int len,link;
int trans[26];
};
struct SAM{
state st[maxn*2];
int siz,last;
void init(){
siz=last=0;
st[0].len=0;
st[0].link=-1;
memset(st[0].trans,0,sizeof(st[0].trans));
}
void init_sta(state sta){
sta.len=sta.link=0;
memset(sta.trans,0,sizeof(sta.trans));
}
void sam_extend(char c){
int cur=++siz;
init_sta(st[cur]);
st[cur].len=st[last].len+1;
int p=last;
while(p!=-1 && st[p].trans[c-'a']==0){
st[p].trans[c-'a']=cur;
p=st[p].link;
}
if(p==-1){
st[cur].link=0;
}
else{
int q=st[p].trans[c-'a'];
if(st[p].len+1==st[q].len){
st[cur].link=q;
}
else{
int clone=++siz;
st[clone].len=st[p].len+1;
st[clone].link=st[q].link;
memcpy(st[clone].trans,st[q].trans,sizeof(st[clone].trans));
while(p!=-1 && st[p].trans[c-'a']==q){
st[p].trans[c-'a']=clone;
p=st[p].link;
}
st[q].link=st[cur].link=clone;
}
}
last=cur;
}
void build(char *s, int n){
init();
for(int i=1;i<=n;i++) sam_extend(s[i]);
}
}sam;
广义后缀自动机
//小写字母版 注意必须init
const int maxn=1e6+5;
struct state{
int len,link,trans[26];
};
struct SAM_BROAD{
state st[maxn*2];
int siz;
void init(){
siz=0;
st[0].len=0;
st[0].link=-1;
memset(st[0].trans,0,sizeof(st[0].trans));
}
void init_sta(state sta){
sta.len=sta.link=0;
memset(sta.trans,0,sizeof(sta.trans));
}
int insert(char ch,int last){
if(st[last].trans[ch-'a']){
int p=last,x=st[last].trans[ch-'a'];
if(st[p].len+1==st[x].len) return x;
else{
int y=++siz;
st[y].len=st[p].len+1;
memcpy(st[y].trans,st[p].trans,sizeof(st[p].trans));
while(p>=0&&st[p].trans[ch-'a']==x){
st[p].trans[ch-'a']=y;
p=st[p].link;
}
st[y].link=st[x].link;
st[x].link=y;
return y;
}
}
int z=++siz,p=last;
init_sta(st[z]);
st[z].len=st[p].len+1;
while(p>=0&&!st[p].trans[ch-'a']){
st[p].trans[ch-'a']=z;
p=st[p].link;
}
if(p==-1) st[z].link=0;
else{
int x=st[p].trans[ch-'a'];
if(st[p].len+1==st[x].len) st[z].link=x;
else{
int y=++siz;
st[y].len=st[p].len+1;
memcpy(st[y].trans,st[x].trans,sizeof(st[x].trans));
while(p>=0&&st[p].trans[ch-'a']==x){
st[p].trans[ch-'a']=y;
p=st[p].link;
}
st[y].link=st[x].link;
st[z].link=st[x].link=y;
}
}
return z;
}
}sam;
网络流相关
最大流
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=305;
struct edge{
int flow,to;
int rev;
};
vector<edge> gra[maxn];
void addedge(int u,int v,int f){
edge tmp;
tmp.flow=f; tmp.to=v;
gra[u].push_back(tmp);
tmp.flow=0; tmp.to=u;
gra[v].push_back(tmp);
int sizu=gra[u].size(),sizv=gra[v].size();
gra[u][sizu-1].rev=sizv-1;
gra[v][sizv-1].rev=sizu-1;
}
int dep[maxn],s,t;
bool bfs(){
memset(dep,0,sizeof(dep));
dep[s]=1;
queue<int> que;
que.push(s);
while(!que.empty()){
int u=que.front();
que.pop();
int siz=gra[u].size();
for(int i=0;i<siz;i++){
edge v=gra[u][i];
int vv=v.to;
if(dep[vv]||!v.flow) continue;
dep[vv]=dep[u]+1;
que.push(vv);
}
}
return dep[t];
}
int now[maxn];
int dfs(int cur,int flow){
if(cur==t||!flow) return flow;
int f;
for(int i=now[cur];i<(int)gra[cur].size();i++){
edge &v=gra[cur][i];
int vv=v.to;
if(dep[vv]==dep[cur]+1&&(f=dfs(vv,min(flow,v.flow)))){
v.flow-=f;
gra[vv][v.rev].flow+=f;
return f;
}
now[cur]=i;
}
return 0;
}
int dinic(){
int flow=0,f;
while(bfs()){
memset(now,0,sizeof(now));
while(f=dfs(s,0x3f3f3f3f)) flow+=f;
}
return flow;
}
最小费用最大流
//int版
#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
const int inf=0x3f3f3f3f;
int n,m;
struct edge{
int flow;
int to,rev;
int cost;
};
vector<edge> gra[maxn];
void addedge(int u,int v,int f,int cost){
edge tmp; tmp.cost=cost;
tmp.flow=f; tmp.to=v;
gra[u].push_back(tmp);
tmp.flow=0; tmp.to=u; tmp.cost=-cost;
gra[v].push_back(tmp);
int sizu=gra[u].size(),sizv=gra[v].size();
gra[u][sizu-1].rev=sizv-1;
gra[v][sizv-1].rev=sizu-1;
}
int dis[maxn],h[maxn];
int s,t;
typedef pair<int,int> pii;
int pre[maxn],prev[maxn];
bool dij(){
memset(dis,0x3f,sizeof(dis));
memset(pre,0,sizeof(pre));
dis[s]=0;
priority_queue<pii,vector<pii>,greater<pii> > que;
que.push(make_pair(0,s));
while(!que.empty()){
pii u=que.top(); que.pop();
int uu=u.second;
int w=u.first;
if(dis[uu]!=w) continue;
for(int i=0;i<(int)gra[uu].size();i++){
edge v=gra[uu][i];
int vv=v.to;
int cost=v.cost;
if(!v.flow)continue;
if(dis[vv]>dis[uu]+cost+h[uu]-h[vv]){
dis[vv]=dis[uu]+cost+h[uu]-h[vv];
que.push(make_pair(dis[vv],vv));
pre[vv]=uu;
prev[vv]=i;
}
}
}
return dis[t]!=inf;
}
int totCost;
int dinic(){
totCost=0;
int flow=0;
memset(h,0,sizeof(h));
while(dij()){
for(int i=1;i<=n;i++)h[i]+=dis[i];
int now=t;
int f=inf;
while(pre[now]){
int id=prev[now];
now=pre[now];
f=min(f,gra[now][id].flow);
}
now=t;
while(pre[now]){
int id=prev[now];
now=pre[now];
gra[now][id].flow-=f;
gra[gra[now][id].to][gra[now][id].rev].flow+=f;
}
flow+=f,totCost+=f*h[t];
}
return flow;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++){
int u,v;
int f,c;
scanf("%d%d%d%d",&u,&v,&f,&c);
addedge(u,v,f,c);
}
int flow=dinic();
printf("%d %d",flow,totCost);
return 0;
}
//long long版
#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n,m;
struct edge{
ll flow;
int to,rev;
ll cost;
};
vector<edge> gra[maxn];
void addedge(int u,int v,ll f,ll cost){
edge tmp; tmp.cost=cost;
tmp.flow=f; tmp.to=v;
gra[u].push_back(tmp);
tmp.flow=0; tmp.to=u; tmp.cost=-cost;
gra[v].push_back(tmp);
int sizu=gra[u].size(),sizv=gra[v].size();
gra[u][sizu-1].rev=sizv-1;
gra[v][sizv-1].rev=sizu-1;
}
ll dis[maxn],h[maxn];
int s,t;
typedef pair<ll,int> pii;
int pre[maxn],prev[maxn];
bool dij(){
memset(dis,0x3f,sizeof(dis));
memset(pre,0,sizeof(pre));
dis[s]=0;
priority_queue<pii,vector<pii>,greater<pii> > que;
que.push(make_pair(0,s));
while(!que.empty()){
pii u=que.top(); que.pop();
int uu=u.second;
ll w=u.first;
if(dis[uu]!=w) continue;
for(int i=0;i<(int)gra[uu].size();i++){
edge v=gra[uu][i];
int vv=v.to;
ll cost=v.cost;
if(!v.flow)continue;
if(dis[vv]>dis[uu]+cost+h[uu]-h[vv]){
dis[vv]=dis[uu]+cost+h[uu]-h[vv];
que.push(make_pair(dis[vv],vv));
pre[vv]=uu;
prev[vv]=i;
}
}
}
return dis[t]!=inf;
}
ll totCost;
ll dinic(){
totCost=0;
ll flow=0;
memset(h,0,sizeof(h));
while(dij()){
for(int i=1;i<=n;i++) if(dis[i]!=inf)h[i]+=dis[i];
int now=t;
ll f=inf;
while(pre[now]){
int id=prev[now];
now=pre[now];
f=min(f,gra[now][id].flow);
}
now=t;
while(pre[now]){
int id=prev[now];
now=pre[now];
gra[now][id].flow-=f;
gra[gra[now][id].to][gra[now][id].rev].flow+=f;
}
flow+=f,totCost+=f*h[t];
}
return flow;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++){
int u,v;
ll f,c;
scanf("%d%d%lld%lld",&u,&v,&f,&c);
addedge(u,v,f,c);
}
ll flow=dinic();
printf("%lld %lld",flow,totCost);
return 0;
}
二分图
匈牙利算法
vector<int> gra[maxn];
void addedge(int u,int v){
gra[u].push_back(v);
gra[v].push_back(u);
}
int match[maxn];
bool used[maxn];
bool dfs(int u){
used[u]=true;
for(int i=0;i<(int)gra[u].size();i++){
int v=gra[u][i];
int w=match[v];
if(!w||!used[w]&&dfs(w)){
match[u]=v;
match[v]=u;
return true;
}
}
return false;
}
int solve(){
int res=0;
memset(match,0,sizeof(match));
for(int i=1;i<=n;i++){
memset(used,0,sizeof(used));
if(dfs(i)) res++;
}
return res;
}