ZJOI 2009 狼和羊的故事 网络流

题目:

“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

思路:

一开始没往网络流想,想了一些乱七八糟的找规律方法,无果。看了标签才想到做法......

将每个格子当做一个点,源点S向所有1连边,所有2向汇点T连边,其边权均为INF;然后0或1向相邻的0或2的点连边,其边权均为1;这样问题转化为使源点不能到达汇点的最小割。权当复习一遍Dinic吧。。。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>

#define For(i,j,k) for(int i = j;i <= (int)k;i++)
#define Forr(i,j,k) for(int i = j;i >= (int)k;i--)
#define Set(i,j) memset(i, j, sizeof(i)) 
#define pb push_back

using namespace std;

const int N = 110, M = N * N;
const int d[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};

int n, m, cnt = 1, Map[N][N], id[N][N];

struct Edge{
	int to, flow, cap;
};

struct Dinic{
	vector<int> G[M];
	int S, T, e;
	int dis[M], cur[M];
	bool vis[M];
	Edge E[M<<4];

	void Add(int x, int y, int f){
		E[e] = (Edge){y, 0, f}, G[x].pb(e++);
		E[e] = (Edge){x, 0, 0}, G[y].pb(e++);
	}

	bool BFS(){
		Set(vis, 0);
		queue<int> q;
		q.push(S);
		vis[S] = 1, dis[S] = 0;
		while(!q.empty()){
			int h = q.front(); q.pop();
			For(i,0,G[h].size() - 1){
				Edge& s = E[G[h][i]];
				if(vis[s.to] || s.flow == s.cap) continue;
				vis[s.to] = 1, dis[s.to] = dis[h] + 1;
				q.push(s.to);
			}
		}
		return vis[T];
	}

	int DFS(int h, int f){
		if(h == T) return f;
		int sum = 0;
		for(int &i = cur[h];i < G[h].size() && sum < f;i++){
			Edge& s = E[G[h][i]];
			int t;
			if(dis[h] + 1 == dis[s.to] && (t = DFS(s.to, min(s.cap - s.flow, f - sum)))){
				sum += t;
				s.flow += t;
				E[G[h][i] ^ 1].flow -= t;
			}
		}
		return sum;
	}

	int Maxflow(int s, int t){
		S = s, T = t;
		int Ans = 0;
		while(BFS()){
			Set(cur, 0);
			Ans += DFS(S, 1e9);
		}
		return Ans;
	}

}S;

int main(){
	scanf("%d%d", &n, &m);
	For(i,1,n) For(j,1,m) scanf("%d", &Map[i][j]), id[i][j] = ++cnt;
	For(i,1,n) For(j,1,m){
		if(Map[i][j] == 1) S.Add(0, id[i][j], 1e9);
		else if(Map[i][j] == 2){
			S.Add(id[i][j], 1, 1e9);
			continue;
		}
		For(v,0,3){
			int x = i + d[v][0], y = j + d[v][1];
			if(Map[x][y] != 1) S.Add(id[i][j], id[x][y], 1);
		}
	}
	printf("%d\n", S.Maxflow(0, 1));
	return 0;
}


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值