#76-【Dinic】危桥

版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/82192227

Description

Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。

请问Alice和Bob能完成他们的愿望吗?

Input

本题有多组测试数据。
每组数据第一行包含7个空格隔开的整数,分别为N、al、a2、an、bl、b2、bn。
接下来是一个N行N列的对称矩阵,由大写字母组成。矩阵的i行j列描述编号i一1和j-l的岛屿间的连接情况,若为“O”则表示有危桥相连:为“N”表示有普通的桥相连:为“X”表示没有桥相连

 

Output

对于每组测试数据输出一行,如果他们都能完成愿望输出“Yes”,否则输出“No”。

Sample Input

4 0 1 1 2 3 1

XOXX

OXOX

XOXO

XXOX

4 0 2 1 1 3 2

XNXO

NXOX

XOXO

OXOX

Sample Output

Yes

No

HINT

4<=N<50,O<=a1, a2, b1, b2<=N-1,1 <=an,bn<=50

要注意的是dinic要跑两次。

#include <iostream>
#include <cstring>
#include <queue>

#define SIZE 210
#define INF 1e+09

using namespace std;

struct edge
{
	int to, cap, reverse;
};

vector<edge> graph[SIZE];
int cur[SIZE], depth[SIZE], a[SIZE][SIZE], sink = 200;

bool bfs(void)
{
	queue<int> q;
	int u, i, v;
	
	memset(depth, -1, sizeof (depth));
	q.push(0);
	depth[0] = 0;
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		if (u == sink)
		{
			return true;
		}
		for (i = 0; i < graph[u].size(); ++i)
		{
			v = graph[u][i].to;
			if ((depth[v] == -1) && (graph[u][i].cap > 0))
			{
				depth[v] = depth[u] + 1;
				q.push(v);
			}
		}
	}
	
	return false;
}

int dfs(int u, int flow)
{
	int i, v, ret = 0, delta;
	
	if ((!flow) || (u == sink))
	{
		return flow;
	}
	for (i = cur[u]; i < graph[u].size(); ++i)
	{
		cur[u] = i;
		edge &temp = graph[u][i];
		v = temp.to;
		if ((depth[v] == depth[u] + 1) && (temp.cap > 0))
		{
			delta = dfs(v, min(flow - ret, temp.cap));
			if (delta > 0)
			{
				ret += delta;
				temp.cap -= delta;
				graph[v][temp.reverse].cap += delta;
				if (ret == flow)
				{
					return ret;
				}
			}
		}
	}
	
	return ret;
}

int dinic(void)
{
	int ret = 0, delta;
	
	while (bfs())
	{
		memset(cur, 0, sizeof (cur));
		delta = dfs(0, INF);
		if (!delta)
		{
			return ret;
		}
		ret += delta;
	}
	
	return ret;
}

void addedge(int u, int v, int cap)
{
	graph[u].push_back({v, cap, graph[v].size()});
	graph[v].push_back({u, 0, graph[u].size() - 1});
	
	return;
}

int main(int argc, char** argv)
{
	int n, a1, a2, an, b1, b2, bn, i, j;
	char c;
	
	while (~scanf("%d%d%d%d%d%d%d", &n, &a1, &a2, &an, &b1, &b2, &bn))
	{
		++a1;
		++a2;
		++b1;
		++b2;
		memset(a, 0, sizeof (a));
		for (i = 0; i < SIZE; ++i)
		{
			graph[i].clear();
		}
		for (i = 1; i <= n; ++i)
		{
			for (j = 1; j <= n; ++j) // 建图
			{
				cin >> c;
				if (c == 'O')
				{
					a[i][j] = 1;
					addedge(i, j, 1);
				}
				else if (c == 'N')
				{
					a[i][j] = 2;
					addedge(i, j, INF);
				}
			}
		}
		addedge(0, a1, an);
		addedge(a2, sink, an);
		addedge(0, b1, bn);
		addedge(b2, sink, bn);
		if (dinic() != an + bn) // A这边要Dinic一次
		{
			printf("No\n");
			continue;
		}
		for (i = 0; i < SIZE; ++i)
		{
			graph[i].clear();
		}
		for (i = 1; i <= n; ++i)
		{
			for (j = 1; j <= n; ++j)
			{
				if (a[i][j] == 1)
				{
					addedge(i, j, 1);
				}
				else if (a[i][j] == 2)
				{
					addedge(i, j, INF);
				}
			}
		}
		addedge(0, a2, an);
		addedge(a1, sink, an);
		addedge(0, b2, bn);
		addedge(b1, sink, bn);
		if (dinic() == an + bn) // B这边也要Dinic一次
		{
			printf("Yes\n");
		}
		else
		{
			printf("No\n");
		}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/82192227
76