网络流学习总结和省选专练SCOI2015小凸玩矩阵

17 篇文章 0 订阅
13 篇文章 0 订阅
这是四川连着第几个年头考二分套网络流了?


虽然这是一个二分图最大匹配,但是我匈牙利写挂了

我太弱了。

好了不瞎扯牛逼了,这个题这么搞:

首先题目就告诉你求第k大最小。

首先这就让人瑟瑟发抖。。。。第k大诶,这种出了就是难题。

但凡事总有意外。

我们知道。这个行列单一模型是二分图常见模型。

zjoi2007矩阵游戏。开山鼻祖,可以玩玩。

还有World Final 2017 碟中谍(Mision Impossible)Wf的第四简单的题,但是做对四个怕不是也就前50了。

就是一个矩阵从二维到三维用贪心和匈牙利就好了。但是我太弱了写不来匈牙利于是写的二分图带权匹配

好的,我们考虑二分。

这实际不难想到。

SCOI2014方伯伯运椰子:残量网络上用消圈定理来验证分数规划。

ZJOI2010贪吃的老鼠:构建网络流模型二分查找满足老鼠吃光的最小代价。

近年来单考网络流的省份不多了。大概还有CQSTC坚持吧。

但是CQOI2014危桥可真不是单一的网络流,这个验证证明很繁琐。

还有一种恶心的题:

以CQOI2010分金币和HAOI2008糖果传递为首。

他们太像网络流了。

乍一看和24题的负载平衡一模一样实际上这是一个数论推导。

随便列几个网络流的题吧:

POI2005-KOS唯一的槽点是他不是二分但却写了个二分一样的题面。

SHSTC2002 舞会这是个错题,所以只能跑匈牙利。

NOI2009 植物大战僵尸 最大权闭合图,当年压轴题要top缩环卡tarjan

ZJOI2010 网络扩容 开山的第一个扩容类网络流题(所以浙江牛逼啊)

ZJOI2009 狼和羊的故事 水题一道,最小割就好了。

SCOI2007 质朴的SCSTC时代的题还是UESTC的亲启题啊,水的一匹。

ZJOI2009 可以归为水题。

SCOI2007 修车。那一年考了两个网络流,修车很经典,难在拆k个点上

NOI2012 美食节,三年过去了,信息学就考的辣么难了,这是和修车一模一样的题,但是要动态开点。

还有就是24题啦。

实际上还有不少ACM的但是记不起出处了,下次有空更新!!(*^▽^*)

SCOI2015的那个代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define N 300*300
#define INF (int)1e9+7
#define ll int
inline void read(ll &x){
	x=0;
	ll f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
} 
struct Front_star{
	int u,v,w,nxt;
}e[N*2];
int cnt=1;
int first[N]={0};
void addedge(int u,int v,int w){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
void add(int u,int v,int w){
	addedge(u,v,w);
	addedge(v,u,0);
}
void clr(){
	memset(first,0,sizeof(first));
	cnt=1;
}
int a[300][300]={0};
int n,m,k;
int S=0;
int T=801;
void build(int minsum){
	for(int i=1;i<=n;i++){
		add(S,i,1);
	}
	for(int j=1;j<=m;j++){
		add(j+n,T,1);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]<=minsum){
				add(i,j+n,1);
			}
		}
	}
}
int d[N]={0};
bool bfs(){
	queue<int> q;
	memset(d,-1,sizeof(d));
	d[S]=1;
	q.push(S);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=first[x];i;i=e[i].nxt){
			int v=e[i].v;
			if(e[i].w&&d[v]==-1){
				d[v]=d[x]+1;
				q.push(v);
			}
		}
	}
	return d[T]!=-1;
}
int dfs(int st,int ed,int nowdat){
	int dat=0;
	if(st==ed){
		return nowdat;
	}
	for(int i=first[st];i;i=e[i].nxt){
		int v=e[i].v;
		if(d[v]==d[st]+1&&e[i].w){
			int now=min(nowdat-dat,e[i].w);
			now=dfs(v,ed,now);
			dat+=now;
			e[i].w-=now;
			e[i^1].w+=now;
			if(nowdat==dat){
				return dat;
			}
		}
	}
	if(!dat){
		d[st]=-2;
	}
	return dat;
}
bool check(int sum){
	int ans=0;
	while(bfs()){
		ans+=dfs(S,T,INF);
	}
//	cout<<ans<<endl;
	if(ans>=n-sum+1){
		return true;
	}
	else{
		return false;
	}
}
int ans;
int main(){
	read(n);
	read(m);
	read(k);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			read(a[i][j]);
		}
	}
	int l=0;
	int r=(int)INF;
	while(l<=r){
		int mid=(l+r)/2;
//		cout<<mid<<" ";
		clr();
		build(mid);
		if(check(k)){
			ans=mid;
			r=mid-1;
		}
		else{
			l=mid+1;
		}
	}
	cout<<ans<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值