poj3592(Tarjan+Spfa)

不知道为什么思路都对了,各种数据都过了,就是wa

思路直接建边,联通缩点,然后对缩点Spfa。貌似传送那块有坑,有肯能传到#或者地图外面。

/*
* this code is made by LinMeiChen
* Problem:
* Type of Problem:
* Thinking:
* Feeling:
*/
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<list>
using namespace std;
typedef long long lld;
typedef unsigned int ud;
#define oo 0x3f3f3f3f
#define maxn 2000
#define maxm 20000
struct Edge
{
	int v, next;
}E[maxm],E2[maxm];
int head[maxn], tol, tol2;
int stack[maxn], top;
int low[maxn], dfn[maxn], instack[maxn];
int id[maxn], num, g_cnt, n;
char map[maxn][maxn];
int value[maxn], dis[maxn], h[maxn], mark[maxn];
int q[maxn], front, rear;

struct Node
{
	int x, y;
}index[maxn];
int d[2][2] = {
	{ 1, 0 }, { 0, 1 } 
};

void Init()
{
	memset(instack, 0, sizeof instack);
	memset(value, 0, sizeof value);
	memset(head, -1, sizeof head);
	memset(low, 0, sizeof low);
	memset(dfn, 0, sizeof dfn);
	memset(h, -1, sizeof h);	
	tol = tol2 = top = num = g_cnt = 0;
}

void add_edge(int u, int v)
{
	E[tol].v = v;
	E[tol].next = head[u];
	head[u] = tol++;
}

void add_edge2(int u, int v)
{
	E2[tol2].v = v;
	E2[tol2].next = h[u];
	h[u] = tol2++;
}

void Tarjan(int u)
{
	low[u] = dfn[u] = ++g_cnt;
	stack[top++] = u;
	instack[u] = 1;
	int v;
	for (int i = head[u]; i != -1; i = E[i].next)
	{
		v = E[i].v;
		if (!dfn[v])
		{
			Tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if (instack[v])
			low[u] = min(low[u], dfn[v]);
	}
	if (dfn[u] == low[u])
	{
		num++;
		do
		{
			id[v = stack[--top]] = num;
			instack[v] = 0;
		} while (u != v);
	}
}

void Reach()
{
	for (int i = 0; i < n; i++)
	if (!dfn[i])
		Tarjan(i);
}

void Spfa(int s)
{
	for (int i = 0; i < n; i++)
	{
		mark[i] = 0;
		dis[i] = 0;
	}
	mark[s] = 1;
	dis[s] = value[s];
	front = rear = 0;
	q[rear++] = s;
	while (front < rear)
	{
		int u = q[front++];
		mark[u] = 0;
		for (int i = h[u]; i != -1; i = E2[i].next)
		{
			int v = E2[i].v;
			if (dis[u] + value[v]>dis[v])
			{
				dis[v] = dis[u] + value[v];
				if (!mark[v])
				{
					q[rear++] = v;
					mark[v] = 1;
				}
			}
		}
	}
}

void FindMaxValue(int x,int y)
{
	int ans = 0;
	for (int i = 0; i < x; i++)
	for (int j = 0; j < y; j++)
	{
		if (isdigit(map[i][j]))
		{
			int temp = i*y + j;
			value[id[temp]] += (int)(map[i][j] - '0');
		}
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = head[i]; j != -1; j = E[j].next)
		{
			int u = i, v = E[j].v;
			if (id[u] != id[v])
				add_edge2(id[u], id[v]);
		}
	}
	Spfa(id[0]);
	for (int i = 1; i <= num; i++)
		ans = max(ans, dis[i]);
	printf("%d\n", ans);
}

int main()
{
	int N, M, T, cnt, k;
	scanf("%d", &T);
	while (T--)
	{
		Init();
		cnt = k = 0;
		scanf("%d%d", &N, &M);
		n = N*M;
		for (int i = 0; i < N; i++)
		{
			scanf("%s", map[i]);
			for (int j = 0; j < M;j++)
			if (map[i][j] == '*')
				k++;
		}
		for (int i = 1; i <= k; i++)
			scanf("%d%d", &index[i].x, &index[i].y);
		cnt = 1;
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M; j++)
			{
				if (map[i][j] == '#')
					continue;
				if (map[i][j] == '*')
				{
					if (map[index[i].x][index[i].y] != '#'&&index[i].x>=0&&index[i].x<N&&index[i].y>=0&&index[i].y<M)
						add_edge(i*M + j, index[cnt].x*M + index[cnt].y);					
					cnt++;
				}
				for (int k = 0; k < 2; k++)
				{
					int x = i + d[k][0];
					int y = j + d[k][1];
					if (x >= 0 && x < N&&y >= 0 && y < M && map[x][y] != '#')
						add_edge(i*M + j, x*M + y);
				}
			}
		}
		Reach();
		FindMaxValue(N, M);
	}
	return 0;
}
/*
2
2 2
11
1*
0 0
10 10
1167811678
1*77811678
1*70001678
1*77811678
1#77800078
1#77837###
1*00037###
1*34000###
1*3451*778
37###1#345
5 5
5 5
5 6
5 7
5 8
5 9
5 10

2
3 3
111
#11
11*
2 0

*/

你可能感兴趣的:(算法,Tarjan,SPFA)