uva563

题意:

每条路只能走一个人,不能在有交叉的点,要保证所有的银行都覆盖住

思路:

如果汇点的容量如果是银行总数那么自然所有的银行都走过了,这要求每个银行都拉成一条容量为1的线,起点通向0,终点通向maxn(自己设定,在边界外),且表格内每个点都通向终点,容量为1,这保证了容量最多是银行数量,且逃跑后每条路只有一个人

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxx = 5005;
const int maxn = 5001;//创造终点
const int flag = 2500;//拆点
const int INF = 0x3f3f3f3f;

struct edge {
	int s, t, f, c;
	edge(int q, int w, int e, int r) {
		s = q;
		t = w;
		f = e;
		c = r;
	}
	edge() {}
};
int dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};

vector<edge>v;
vector<int> g[maxx];//给个起点的终点在v中下标
int n, m, l;
void add(int from, int to) {
	v.push_back((edge){from, to, 0, 1});
	v.push_back((edge){to, from, 0, 0});
	int len = v.size();
	g[from].push_back(len-2);
	g[to].push_back(len-1);
	
}

void init() {
	for(int i=0; i<=n*n; i++) g[i].clear();
	v.clear();
}
void input2() {
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			if(i==1 || i==n || j==1 || j==m)//边界通向终点
				add((i-1)*m+flag+j, maxn);
			add((i-1)*m+j, (i-1)*m+flag+j);
			for(int k=0; k<4; k++) {
				int x = i+dir[k][0];
				int y = j+dir[k][1];
				if(x<1 || x>n) continue;
				if(y<1 || y>m) continue;
				add((i-1)*m+j+flag, (x-1)*m+y);
			}
		}
	int x, y;
	for(int i=0; i<l; i++) {
		scanf("%d%d", &x, &y);
		add(0, (x-1)*m+y);
	}
}


int ek2() {
	int p[maxx];
	int a[maxx];
	int ans = 0;
	memset(p, 0, sizeof(p));
	queue<int>q;
	while(1) {
		memset(a, 0, sizeof(a));
		a[0] = INF;
		q.push(0);
		while(!q.empty()) {
			int u = q.front();
			q.pop();
			for(int i=0; i<g[u].size(); i++) {
				edge& w = v[g[u][i]];
				if(!a[w.t] && w.c>w.f) {
					//printf("%d   %d\n", u, w.s);
					a[w.t] = min(a[u], w.c-w.f);
					p[w.t] = g[u][i];
					q.push(w.t);
				}
			}
		}
		if(a[maxn]==0) break;
		ans += a[maxn];
		for(int i=maxn; i; i=v[p[i]].s) {
			v[p[i]].f += a[maxn];
			v[p[i]^1].f -= a[maxn];
		}
	}
	return ans;

	
}

				
int main() {
	int kase;
	scanf("%d", &kase);
	while(kase--) {
		scanf("%d%d%d", &n, &m, &l);
		init();
		input2();
		int ans = ek2();
		if(ans == l) printf("possible\n");
		else printf("not possible\n");

	}
	return 0;
}
		

有一个很奇怪的地方:

a[w.t] = min(a[w.s], w.c-w.f) 是超时的

我试着打出来 w.s与u,他们是一样的,不知道为什么就朝超时了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值