pku 3592 强连通+缩点+floodfill

#include <iostream>
#include <cstdio>
using namespace std;

const int MAXN = 41;
int n, m, k, eid, res, eido;
char MAP[MAXN][MAXN];
int magf[MAXN][MAXN], magt[MAXN*MAXN];
int revf[MAXN][MAXN], revt[MAXN*MAXN];
int ids[MAXN*MAXN], path[MAXN*MAXN], Time, len;
int p0[MAXN*MAXN], p1[MAXN*MAXN], p2[MAXN*MAXN], sores[MAXN*MAXN];
int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int dist[MAXN*MAXN];
bool vist[MAXN*MAXN];
bool hash[MAXN*MAXN][MAXN*MAXN];

struct Edge
{
	int f,v, next, cost;
};
Edge e[MAXN*MAXN];
Edge orie[MAXN*MAXN*10], orit[MAXN*MAXN*10];

void insert(int from, int to, int cost)
{
	e[eid].f = from;
	e[eid].v = to;
	e[eid].cost = cost;
	e[eid].next = p0[from];
	p0[from] = eid++;
}

void insert_ori(int from, int to)
{
	orie[eido].v = to;
	orie[eido].next = p1[from];
	p1[from] = eido;

	orit[eido].v = from;
	orit[eido].next = p2[to];
	p2[to] = eido++;
}

void dfs(int pos)
{
	int i;
	vist[pos] = true;
	for (i = p1[pos]; i != -1; i = orie[i].next)
	{
		if (!vist[orie[i].v])
		{
			dfs(orie[i].v);
		}
	}
	path[len++] = pos;
}

void dfs_reverse(int pos)
{
	vist[pos] = true;
	ids[pos] = Time;
	int x = pos/m, y = pos%m;
	if (MAP[x][y] >= '1' && MAP[x][y] <= '9')
	{
		sores[Time] += MAP[x][y]-'0';
	}

	int i;
	for (i = p2[pos]; i != -1; i = orit[i].next)
	{
		if (!vist[orit[i].v])
		{
			dfs_reverse(orit[i].v);
		}
	}
}

void floodfill()
{
	bool flag = true;
	int i;
	for (i = 1; i < Time; ++i)
	{
		dist[i] = 0;
	}
	while (flag)
	{
		flag = false;
		for (i = 0; i < eid; ++i)
		{
			if (dist[e[i].v] + e[i].cost > dist[e[i].f])
			{
				dist[e[i].f] = dist[e[i].v] + e[i].cost;
				flag = true;
			}
		}
	}
	printf("%d\n", dist[ids[0]]+res);
}

void debug()
{
	int i, j;
	for (i = 0; i < n; ++i)
	{
		for (j = 0; j < m; ++j)
		{
			printf("%d ", ids[i*m+j]);
		}
		printf("\n");
	}
}

void solution()
{
	len = 0, Time = 1;
	int i, j, q, fx, fy;
	for (i = 0; i < n*m; ++i)
	{
		vist[i] = false;
		ids[i] = 0;
	}
	for (i = 0; i < n; ++i)
	{
		for (j = 0; j < m; ++j)
		{
			if (!vist[i*m+j] && MAP[i][j] != '#')
			{
				dfs(i*m+j);
			}
		}
	}

	for (i = 0; i < n*m; ++i)
	{
		vist[i] = false;
	}
	sores[0] = 0;
	for (i = len-1; i >= 0; --i)
	{
		int x, y;
		x = path[i]/m;
		y = path[i]%m;
		if (!vist[path[i]] && MAP[x][y] != '#')
		{
			sores[Time] = 0;
			dfs_reverse(path[i]);
			Time++;
		}
	}
//	debug();
	for (i = 1; i < Time; ++i)
	{
		p0[i] = -1;
		for (j = 1; j < Time; ++j)
		{
			hash[i][j] = false;
		}
	}
	eid = 0;
	res = sores[ids[0]];
	for (i = 0; i < n; ++i)
	{
		for (j = 0; j < m; ++j)
		{
			if (MAP[i][j] != '#')
			{
				for (q = 0; q < 2; ++q)
				{
					fx = i + dir[q][0];
					fy = j + dir[q][1];
					if (fx >= 0 && fx < n && fy >= 0 && fy < m && MAP[fx][fy] != '#')
					{
						if (ids[fx*m+fy] != ids[i*m+j] && !hash[ids[i*m+j]][ids[fx*m+fy]])
						{
							hash[ids[i*m+j]][ids[fx*m+fy]] = true;
							insert(ids[i*m+j], ids[fx*m+fy], sores[ids[fx*m+fy]]);
						}
					}
				}
				if (MAP[i][j] == '*')
				{
					int pot = magt[magf[i][j]];
					fx = pot/m;
					fy = pot%m;
					if (MAP[fx][fy] != '#')
					{
						if (ids[i*m+j] != ids[fx*m+fy] && !hash[ids[i*m+j]][ids[fx*m+fy]])
						{
							hash[ids[i*m+j]][ids[fx*m+fy]] = true;
							insert(ids[i*m+j], ids[fx*m+fy], sores[ids[fx*m+fy]]);
						}
					}
				}
			}
		}
	}

	floodfill();
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d %d", &n, &m);
		int i, j, q;
		k = 0;
		for (i = 0; i < n; ++i)
		{
			for (j = 0; j < m; ++j)
			{
				revf[i][j] = -1;
			}
		}
		getchar();
		for (i = 0; i < n; ++i)
		{
			gets(MAP[i]);
			for (j = 0; j < m; ++j)
			{
				if (MAP[i][j] == '*')
				{
					magf[i][j] = k;
					revt[k++] = i*m+j;
				}
			}
		}
		eido = 0;
		memset(p1, -1, sizeof(p1));
		memset(p2, -1, sizeof(p2));
		for (i = 0; i < k; ++i)
		{
			int x, y;
			scanf("%d %d", &x, &y);
			magt[i] = x*m+y;
			revf[x][y] = i;
			insert_ori(revt[i], magt[i]);
		}
		
		for (i = 0; i < n; ++i)
		{
			for (j = 0; j < m; ++j)
			{
				if (MAP[i][j] != '#')
				{
					for (q = 0; q < 2; ++q)
					{
						int fx, fy;
						fx = i + dir[q][0];
						fy = j + dir[q][1];
						if (fx >= 0 && fx < n && fy >= 0 && fy < m && MAP[fx][fy] != '#')
						{
							insert_ori(i*m+j, fx*m+fy);
						}
					}
				}
			}
		}
		solution();
	}
	return 0;
}

posted on 2010-05-26 21:23  ZAFU_VA  阅读(347)  评论(0编辑  收藏  举报

导航