一名苦逼的OIer,想成为ACMer

Iowa_Battleship

POJ1325 Machine Schedule

原题链接

对于每个任务,要么选\(A\)机器的模式,要么选\(B\)机器的模式,由此想到二分图最小点覆盖。
所以我们可以将任务作为边,将对应的\(A\)机器模式和\(B\)机器模式连起来,然后直接求最小覆盖即可。
注意,本题模式从\(0\)开始编号,而且机器初始是在\(0\)模式,所以在连边时要忽略含\(0\)模式的任务。

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 210;
const int M = 1010;
int fi[N], di[M], ne[M], mtc[N], l;
bool v[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return  p ? -x : x;
}
inline void add(int x, int y)
{
	di[++l] = y;
	ne[l] = fi[x];
	fi[x] = l;
}
bool dfs(int x)
{
	int i, y;
	for (i = fi[x]; i; i = ne[i])
		if (!v[y = di[i]])
		{
			v[y] = 1;
			if (!mtc[y] || dfs(mtc[y]))
			{
				mtc[y] = x;
				return true;
			}
		}
	return false;
}
int main()
{
	int i, x, y, n, m, k, s;
	while (1)
	{
		n = re();
		if (!n)
			return 0;
		m = re();
		k = re();
		memset(fi, 0, sizeof(fi));
		memset(mtc, 0, sizeof(mtc));
		l = s = 0;
		for (i = 1; i <= k; i++)
		{
			re();
			x = re();
			y = re();
			if (x && y)
				add(x, y + n);
		}
		for (i = 1; i <= n; i++)
		{
			memset(v, 0, sizeof(v));
			if (dfs(i))
				s++;
		}
		printf("%d\n", s);
	}
	return 0;
}

posted on 2018-09-14 12:50  Iowa_Battleship  阅读(77)  评论(0编辑  收藏  举报

导航