ybtoj Au 网络流

前言中的前言

  1. 由于本人过菜,有些题解会咕掉,请原谅这个蒟蒻

  2. 由于本人过菜,不知道什么时候就 AFO 了,想给这个机房留下点什么……

  3. 如果想看高效进阶的题解,建议出门左拐,去云落那里看看,保证是全网最全最好的,但不要对云落的博客好奇,更不要看云落的一言 和 云落的合集:黑夜刀己,白日爱人

  4. 如果解决了题解里本蒟蒻的问题,将会获得任意奖励一份(不一定是物质哦),就比如这篇题解就有一个问题

正片开始!

好耶!!!(泪目)

题面

题目传送门

前言

网络流 T1,板子题

正文

请自便

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf=1e9+9;
const int N=1e5+5;
int n,m,s,t,head[N],cnt=1;
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	e[cnt].w=w;
	head[u]=cnt;
}
int now[N],deep[N];
int bfs(){
	for(int i=1;i<=n;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w>0&&deep[v]==inf){
				q.push(v);
				now[v]=head[v];
				deep[v]=deep[u]+1;
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];i>0&&sum>0;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w>0&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(k==0)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
signed main(){
	cin>>m>>n;
	s=1,t=n;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w),add(v,u,0);
	}
	int ans=0;
	while(bfs())ans+=dfs(s,inf);
	cout<<ans;
	return 0;
}

后记

好难好难

题面

题目传送门

前言

网络流 T2,应用题

正文

建立虚拟源点和汇点;

对于每一个人能开的保险柜, 如果它没有被打开过, 则从虚拟源点到当前的人连一条流量为保险柜金币数量的边, 表示这个人可以从这个保险柜中卷走所有的金币;

对于每一个人能开的保险柜, 如果它已经被打开过了, 则从上一次可以开这个保险柜的人到当前的人连一条流量为无限大的边, 表示当前的人可以无限从上一个人索取金币;

对于每个人, 向汇点连一条流量为其想要的金币的数量。

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
const int inf=1e9+9;
int m,n,s,t,cnt=1;
int c[N],last[N],head[N];
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
int now[N],deep[N];
int bfs(){
	for(int i=s;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w>0&&deep[v]==inf){
				q.push(v);
				now[v]=head[v];
				deep[v]=deep[u]+1;
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];~i&&sum>0;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w>0&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(k==0)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
signed main(){
	cin>>m>>n;
	t=n+1;
	for(int i=s;i<=t;i++)head[i]=-1;
	for(int i=1;i<=m;i++)cin>>c[i];
	for(int i=1;i<=n;i++){
		int a,b,id;
		cin>>a;
		while(a--){
			cin>>id;
			if(!last[id]){
				add(s,i,c[id]);
				add(i,s,0);
			}else{
				add(last[id],i,inf);
				add(i,last[id],0);
			}
			last[id]=i;
		}
		cin>>b;
		add(i,t,b);
		add(t,i,0);
	}
	int ans=0;
	while(bfs()){
		ans+=dfs(s,inf);
	}
	cout<<ans;
	return 0;
}

后记

好难好难

题面

题目传送门

前言

网络流 T3,应用题

正文

推个式子

不想写了

详见

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+10;
int T,n,m,a[45][45],b,w,cnt=1;
int id(int x,int y){
	return (x-1)*m+y;
}
int head[N];
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	e[cnt].w=w;
	head[u]=cnt;
}
int dx[5]={0,0,1,0,-1};
int dy[5]={0,1,0,-1,0};
int V,s,t,deep[N],now[N];
int bfs(){
	for(int i=s;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int>q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				q.push(v);
				now[v]=head[v];
				deep[v]=deep[u]+1;
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];~i&&sum;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(k==0)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
int ans;
bool check(int x){
	memset(head,-1,sizeof(head));
	memset(now,0,sizeof(now));
	V=0;
	cnt=1;
	s=0,t=id(n,m)+1;
	ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			//if(x-a[i][j]<0) return 0;
			if((i+j)%2==0){V+=x-a[i][j];
				add(s,id(i,j),x-a[i][j]);
				///cout<<s<<" "<<id(i,j)<<endl;
				add(id(i,j),s,0);
				for(int k=1;k<=4;k++){
					int xx=i+dx[k],yy=j+dy[k];
					if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
						add(id(i,j),id(xx,yy),inf);
						//cout<<id(i,j)<<" "<<id(xx,yy)<<endl;
						add(id(xx,yy),id(i,j),0);
					}
				}
			}else{
				add(id(i,j),t,x-a[i][j]);
				//cout<<id(i,j)<<" "<<t<<endl;
				add(t,id(i,j),0);
			}
		}
	}
	while(bfs()){
		ans+=dfs(s,inf);
	}
	if(ans==V)return 1;
	return 0;
}
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m;
		b=0,w=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>a[i][j];
				if((i+j)%2==0)b+=a[i][j];
				else w+=a[i][j];
			}
		}
		if(n%2&&m%2){
			int x=b-w;
			if(check(x))cout<<(n*m/2+1)*x-b<<endl;
			else cout<<-1<<endl;
			continue;
		}
		if(b!=w){cout<<-1<<endl;continue;}
		int l=1,r=inf,an=-1;
		while(l<=r){
			int mid=(l+r)>>1;
			//cout<<mid<<endl;
			if(check(mid))r=mid-1,an=mid;
			else l=mid+1;
		}
		if(an==-1)cout<<-1<<endl;
		else cout<<an*(n*m/2)-b<<endl;
	}
	return 0;
}

后记

调了一下午+一晚上没调出来,云落 5 分钟调出来了

https://www.luogu.com.cn/problem/solution/P3163

https://www.luogu.com.cn/problem/solution/P2472

posted @   小惰惰  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
/* 鼠标点击求赞文字特效 */
点击右上角即可分享
微信分享提示

目录导航