模板小记3

匈牙利算法

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#define mp(x,y) make_pair((x),(y))
using namespace std; 
const int N=1e5+5; 
struct node{
	int y,nt; 
}a[N*2]; 
int n,m,E,head[N],tot,link[N];
bool v[N];  
map<pair<int,int>,bool>b; 
void add(int x,int y){
	a[++tot]=(node){y,head[x]}; head[x]=tot; 
}
bool hungry(int x){
	for(int i=head[x];i;i=a[i].nt){
		int y=a[i].y; 
		if (!v[y]){
			v[y]=1; 
			int q=link[y]; 
			link[y]=x; 
			if (!q||hungry(q)) return 1; 
			link[y]=q; 
		}
	}
	return 0; 
}
int main(){
	scanf("%d%d%d",&n,&m,&E); 
	for(int i=1;i<=E;i++){
		int x,y; 
		scanf("%d%d",&x,&y); 
		if (!b[mp(x,y)]) add(x,y); else b[mp(x,y)]=1; 
	}
	int ans=0; 
	for(int i=1;i<=n;i++) {
		memset(v,0,sizeof(v)); 
		if (hungry(i)) ans++;
	}
	printf("%d",ans); 
	return 0; 
}

离散化

	sort(Q+1,Q+1+q); 
	q=unique(Q+1,Q+1+q)-Q-1; 
	rep(i,1,m){
		d[i]=lower_bound(Q+1,Q+q+1,d[i])-Q; 

最长公共上升子序列

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; 
const int N=1e5+5; 
int n,belong[N],b[N],len; 
int main(){
	scanf("%d",&n); 
	int x; 
	for(int i=1;i<=n;i++)  scanf("%d",&x),belong[x]=i; 
	for(int i=1;i<=n;i++){
		scanf("%d",&x); 
		if (belong[x]>b[len]) b[++len]=belong[x]; 
		else b[lower_bound(b+1,b+len+1,belong[x])-b]=belong[x]; 
	}
	printf("%d",len); 
	return 0; 
}

单调栈

#include<cstdio> 
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std; 
const int N=3e6+5; 
stack<int>sk;
int n,f[N],d[N]; 
int main(){
	scanf("%d",&n); 
	for(int i=1;i<=n;i++) scanf("%d",&f[i]); 
	for(int i=1;i<=n;i++){
		while (sk.size()&&f[sk.top()]<f[i]) d[sk.top()]=i,sk.pop();
		sk.push(i); 
	}
	for(int i=1;i<=n;i++) printf("%d ",d[i]);
	return 0; 
}

博弈

.。。。。。。。

康拓展开

在这里插入图片描述

最小表示法

#include<cstdio>
#include<algorithm>
using namespace std; 
int n,a[600010],ans; 
int main()
{
	scanf("%d",&n); 
	for (int w=1;w<=n;w++) scanf("%d",&a[w]),a[w+n]=a[w]; 
	int i=1,j=2,k=0; 
	while (i<=n&&j<=n)
	{
		k=0; while (k<=n&&a[i+k]==a[j+k])k++; 
		if (k==n) break; 
		if (a[i+k]>a[j+k]) {i=i+k+1; if (i==j) i++;} 
		else {j=j+k+1; if (i==j) j++;}
	}
	ans=min(i,j); 
	for (int w=ans;w<=ans+n-1;w++)
	 printf("%d ",a[w]); 
}

缩点

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; 
const int N=1e5+5; 
struct node{
	int x,y,nt; 
}a[N*2]; 
struct node1{
	int y,nt; 
}A[N*2];
int cnt,n,m,p[N],low[N],dfn[N],s[N],belong[N]; 
int tot,head[N],head1[N],tot1;
queue<int>q; 
int dis[N],in[N]; 
void add(int x,int y){
	a[++tot]=(node){x,y,head[x]}; head[x]=tot; 
}
void add1(int x,int y){
	A[++tot1]=(node1){y,head1[x]}; head1[x]=tot1; in[y]++; 
}
int num;
bool B[N]; 
void tarjan(int x){
	low[x]=dfn[x]=++cnt; 
	s[++num]=x; B[x]=1; 
	for(int i=head[x];i;i=a[i].nt){
		int y=a[i].y; 
		if (!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); 
		else if (B[y]) low[x]=min(low[x],dfn[y]); 
	}
	if (dfn[x]==low[x]){
		int y; 
		while (y=s[num--]){
			belong[y]=x; 
			B[y]=0; 
			if (x==y) break;
			p[x]+=p[y]; 
		}
	}
}
int topo(){
	while (q.size()) q.pop(); 
	for(int i=1;i<=n;i++) if (belong[i]==i&&!in[i]) q.push(i),dis[i]=p[i];
	while (q.size()){
		int x=q.front(); q.pop(); 
		for(int i=head1[x];i;i=A[i].nt){
			int y=A[i].y;
			dis[y]=max(dis[y],dis[x]+p[y]); 
			in[y]--; 
			if (!in[y]) q.push(y); 
		}
	}
	int ans=0; 
	for(int i=1;i<=n;i++) ans=max(ans,dis[i]); 
	return ans; 
}
int main(){
	scanf("%d%d",&n,&m); 
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
	for(int i=1;i<=m;i++){
		int x,y; 
		scanf("%d%d",&x,&y); 
		add(x,y); 
	}
	for(int i=1;i<=n;i++) if (!dfn[i]) tarjan(i); 
	for(int i=1;i<=tot;i++) if (belong[a[i].x]!=belong[a[i].y]) add1(belong[a[i].x],belong[a[i].y]);
	printf("%d",topo()); 
	return 0; 
}

割点


void tarjan(int x){
	low[x]=dfn[x]=++cnt; 
	s[++num]=x; B[x]=1; 
//	int flag=0;
	for(int i=head[x];i;i=a[i].nt){
		int y=a[i].y; 
		if (!dfn[y]){
	        tarjan(y),low[x]=min(low[x],low[y]); /*
	        if (low[y]>=dfn[x]){
	        	flag++; 
	        	if (x!=root&&flag>1) bb[x]=1; 
			}*/
		}
		else if (B[y]) low[x]=min(low[x],dfn[y]); 
	}
	
}

最大流

#include<cstdio> 
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long 
using namespace std; 
const ll N=2e5+5,inf=1e18; 
struct node{
	ll y,z,nt; 
}a[N];
ll tot=1,head[N],dep[N],cur[N]; //tot=-1 or tot=1
ll n,m,s,t; 
void add(ll x,ll y,ll z){
	a[++tot]=(node){y,z,head[x]}; head[x]=tot; 
	a[++tot]=(node){x,0,head[y]}; head[y]=tot; 
}
queue<ll>q; 

bool bfs(){
	memset(dep,0,sizeof(dep)); 
	while (q.size()) q.pop(); 
	q.push(s); dep[s]=1; 
	while (q.size()){
		ll x=q.front(); q.pop(); 
		for(ll i=head[x];i;i=a[i].nt){
			ll y=a[i].y; 
			if (a[i].z&&!dep[y]){
				dep[y]=dep[x]+1; 
				if (y==t) return 1; 
				q.push(y); 
			}
		}
	}
	return 0; 
}
ll dinic(ll x,ll maxf){
	if (x==t||!maxf) return maxf; 
	ll ret=0; 
	for(ll &i=cur[x];i;i=a[i].nt){
		ll y=a[i].y; 
		if (a[i].z&&dep[y]==dep[x]+1){
			ll ff=dinic(y,min(a[i].z,maxf-ret)); 
			a[i].z-=ff; 
			a[i^1].z+=ff; 
			ret+=ff; 
			if (ret==maxf) break;
		}
	}
	return ret; 
}
int main(){
	scanf("%lld%lld%lld%lld",&n,&m,&s,&t); 
	for(ll i=1;i<=m;i++){
		ll x,y,z; 
		scanf("%lld%lld%lld",&x,&y,&z); 
		add(x,y,z); 
	}
	ll ans=0; 
	while (bfs()) {
		for(ll i=1;i<=n;i++) cur[i]=head[i]; 
		ans+=dinic(s,inf); 
	}
	printf("%lld",ans); 
	return 0; 
}

最小费用最大流

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std; 
const int N=1e5+5,inf=0x3f3f3f3f; 
struct node{
	int y,coat,z,nt; 
}a[N*2];
int tot=1,head[N]; 
int n,m,s,t; 
void add(int x,int y,int coat,int z){
	a[++tot]=(node){y,coat,z,head[x]}; head[x]=tot; 
	a[++tot]=(node){x,-coat,0,head[y]}; head[y]=tot; 
}
int maxflow,ans,d[N],pre[N],inc[N];
bool vis[N]; 
bool spfa(){
	queue<int>q; 
	memset(d,0x3f,sizeof(d)); 
	memset(vis,0,sizeof(vis)); 
	q.push(s); d[s]=0; vis[s]=1; inc[s]=inf; 
	while(q.size()){
		int x=q.front(); q.pop(); 
		for(int i=head[x];i;i=a[i].nt){
			int y=a[i].y; 
			if (a[i].z==0) continue;  // important 
			if (d[y]>d[x]+a[i].coat){
				d[y]=d[x]+a[i].coat; 
				inc[y]=min(inc[x],a[i].z); 
				pre[y]=i; 
				if (!vis[y]) vis[y]=1,q.push(y); 
			}
		}
		vis[x]=0; 
	}
	return (d[t]==inf)?0:1; 
}
void update(){
	int x=t; 
	while(x!=s){
		int i=pre[x]; a[i].z-=inc[t]; a[i^1].z+=inc[t]; x=a[i^1].y; 
	}
	maxflow+=inc[t]; ans+=d[t]*inc[t]; 
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t); 
	for(int i=1;i<=m;i++){
		int x,y,coat,z; 
		scanf("%d%d%d%d",&x,&y,&z,&coat); 
		add(x,y,coat,z); 
	}
	while (spfa()) update(); 
	printf("%d %d",maxflow,ans); 
	return 0; 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值