HUST 1027 Enemy Target!

Description

In the Game Red Alert, a group of soviet infantry marches towards our base. And we have N Prism Tanks to defend our base. Suppose the coming infantry marches in a ROW*COLUMN rectangle grid, and keeps the shape unchanged. A Prism Tank can eliminate infantry in any row or column at a shot. Prism Tank is weak in self-defense, so your task is to assign the least Prism Tanks, fire simultaneously to eliminate all the invading enemies. If our Prism Tank is enough, submit any assignment using the least Prism Tanks. Otherwise, report it.

Input

First line: 3 integers ROW,COLUMN,N--number of Prism Tanks we have now(ROW<=1000, COLUMN<=1000,N<=1000). Line 2 to ROW+1: Each line is a binary 01 string with length COLUMN, represent the shape of infantry. Set 1 if a position have a soldier, otherwise 0.

Output

If there exist an assignment, output it in the format: k1+k2 ROW: R1 R2...Rk1 COLUMN: C1 C2...Ck2 k1+k2 is the totoal number of Prism Tanks. Otherwise print one line "NOT ENOUGH TANK".

Sample Input

4 4 4
0101
1010
1010
0010

Sample Output

3
ROW: 1

COLUMN: 1 3

二分图的最小点集覆盖,这题还需要求出是那些点,直接贪心的方案是错的

具体的办法详见正解,顺便附上本人代码。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<iostream>
#include<stack>
#include<algorithm>
#include<bitset>
#include<functional>
#include<ctime>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int maxn = 1e3 + 10;
const int INF = 0x7FFFFFFF;
int n, m, k, flag[maxn * 2], ans;
char s[maxn];

struct MaxFlow
{
	const static int maxe = 2e6 + 10;    //边数
	const static int maxp = 1e5 + 10;   //点数
	const static int INF = 0x7FFFFFFF;
	struct Edges
	{
		int x, f;
		Edges(){}
		Edges(int x, int f) :x(x), f(f){}
	}edge[maxe];
	int first[maxp], next[maxe], dis[maxp], tot, work[maxp], n;

	void clear(int x){ n = x; tot = 0; for (int i = 0; i <= n; i++) first[i] = -1; }

	void AddEdge(int s, int t, int f)
	{
		edge[tot] = Edges(t, 0); next[tot] = first[s]; first[s] = tot++;
		edge[tot] = Edges(s, f); next[tot] = first[t]; first[t] = tot++;
	}

	bool bfs(int s, int t)
	{
		for (int i = 0; i <= n; i++) dis[i] = -1;
		queue<int> p;    p.push(s);    dis[s] = 0;
		while (!p.empty())
		{
			int q = p.front();    p.pop();
			for (int i = first[q]; i != -1; i = next[i])
			{
				if (edge[i ^ 1].f&&dis[edge[i].x] == -1)
				{
					p.push(edge[i].x);
					dis[edge[i].x] = dis[q] + 1;
					if (dis[t] != -1) return true;
				}
			}
		}
		return false;
	}

	int dfs(int s, int t, int low)
	{
		if (s == t) return low;
		for (int &i = work[s], x; i >= 0; i = next[i])
		{
			if (dis[s] + 1 == dis[edge[i].x] && edge[i ^ 1].f && (x = dfs(edge[i].x, t, min(low, edge[i ^ 1].f))))
			{
				edge[i].f += x;    edge[i ^ 1].f -= x;	return x;
			}
		}
		return 0;
	}

	int dinic(int s, int t)
	{
		int maxflow = 0, inc = 0;
		while (bfs(s, t))
		{
			for (int i = 0; i <= n; i++) work[i] = first[i];
			while (inc = dfs(s, t, INF)) maxflow += inc;
		}
		return maxflow;
	}
	void dfs(int x, int y)
	{
		if (flag[x] >= 0 || !x || x == n) return;
		flag[x] = y;
		for (int i = first[x]; i != -1; i = next[i]) dfs(edge[i].x, y ^ 1);
	}
	void find(int a, int b)
	{
		memset(flag, -1, sizeof(flag));
		for (int i = first[0]; i != -1; i = next[i])
		{
			if (!edge[i].f) dfs(edge[i].x, 0);
		}
		for (int i = 1; i <= a; i++) if (flag[i] == -1) flag[i] = 1;
		for (int i = a + 1; i <= a + b; i++) if (flag[i] == -1) flag[i] = 0;
		printf("ROW:");
		for (int i = 1; i <= a; i++) if (flag[i]) printf(" %d", i);
		printf("\nCOLUMN:");
		for (int i = a + 1; i <= a + b; i++) if (flag[i]) printf(" %d", i - a);
		printf("\n");
	}
}solve;

int main()
{
	while (scanf("%d%d%d", &n, &m, &k) != EOF)
	{
		solve.clear(n + m + 1);
		for (int i = 1; i <= n; i++) solve.AddEdge(0, i, 1);
		for (int i = 1; i <= m; i++) solve.AddEdge(n + i, n + m + 1, 1);
		for (int i = 1; i <= n; i++)
		{
			scanf("%s", s + 1);
			for (int j = 1; j <= m; j++)
			{
				if (s[j] == '1') solve.AddEdge(i, n + j, 1);
			}
		}
		if ((ans = solve.dinic(0, n + m + 1)) > k) printf("NOT ENOUGH TANK\n");
		else printf("%d\n", ans), solve.find(n, m);
	}
	return 0;
}



你可能感兴趣的:(Hust)