模板

上次电脑硬盘坏了,整理几个月的模板顷刻间灰飞烟灭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;
}
posted @ 2020-07-28 00:22  rain_star  阅读(113)  评论(0编辑  收藏  举报