A map with a number indicates that there are digits and minerals on it. * indicates that this point can be transferred to another point. # indicates that it cannot be taken. Only the lower and right sides of a vertex can be reached. Now, starting from (0, 0), ask how many minerals can be collected at most.
Train of Thought: This question must be illustrated, and then the longest path, the key is that with the transfer, it is possible to form a right ring, and then it will die in the spfa process. The ownership value on a ring can only be obtained once. So we use Tarjan to find all the rings, accumulate the weights, change them to a vertex, and then create a new graph. The resulting figure is the topology, and spfa can be carefree without loops.
PS: I cannot solve this problem by using Topology Sorting. Please tell me why !!!
Code:
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 20010using namespace std;int cases;int m,n;char src[50][50];int transmit[MAX],points;int head[MAX],total;int next[MAX],aim[MAX];int dfn[MAX],low[MAX],_clock;int stack[MAX],top;bool in_stack[MAX];int changed[MAX],scc,val[MAX];int a[MAX];int _head[MAX],_total;int _next[MAX],_aim[MAX];int f[MAX];bool v[MAX];inline void Initialize(){total = _total = _clock = top = points = scc = 0;memset(head,0,sizeof(head));memset(_head,0,sizeof(_head));memset(dfn,0,sizeof(dfn));memset(in_stack,false,sizeof(in_stack));memset(val,0,sizeof(val));}inline void Add(int x,int y){next[++total] = head[x];aim[total] = y;head[x] = total;}inline void _Add(int x,int y){_next[++_total] = _head[x];_aim[_total] = y;_head[x] = _total;}void Tarjan(int x){dfn[x] = low[x] = ++_clock;in_stack[x] = true;stack[++top] = x;for(int i = head[x]; i; i = next[i]) {if(!dfn[aim[i]])Tarjan(aim[i]),low[x] = min(low[x],low[aim[i]]);else if(in_stack[aim[i]])low[x] = min(low[x],dfn[aim[i]]);}if(dfn[x] == low[x]) {scc++;int temp;do {temp = stack[top--];changed[temp] = scc;in_stack[temp] = false;val[scc] += a[temp];}while(temp != x);}}inline void SPFA(){static queue<int> q;while(!q.empty()) q.pop();memset(f,0,sizeof(f));memset(v,false,sizeof(v));f[changed[0]] = val[changed[0]];q.push(changed[0]);while(!q.empty()) {int x = q.front(); q.pop();v[x] = false;for(int i = _head[x]; i; i = _next[i])if(f[_aim[i]] < f[x] + val[_aim[i]]) {f[_aim[i]] = f[x] + val[_aim[i]];if(!v[_aim[i]]) {v[_aim[i]] = true;q.push(_aim[i]);}}}}int main(){for(cin >> cases; cases; --cases) {scanf("%d%d",&n,&m);Initialize();for(int i = 0; i < n; ++i)scanf("%s",src[i]);for(int i = 0; i < n; ++i)for(int x,y,j = 0;j < m; ++j)if(src[i][j] == '*') {scanf("%d%d",&x,&y);a[i * m + j] = 0;if(src[x][y] != '#')Add(i * m + j,x * m + y);if(i + 1 < n && src[i + 1][j] != '#')Add(i * m + j,(i + 1) * m + j);if(j + 1 < m && src[i][j + 1] != '#')Add(i * m + j,i * m + j + 1);}else if(src[i][j] != '#') {a[i * m + j] = src[i][j] - '0';if(i + 1 < n && src[i + 1][j] != '#')Add(i * m + j,(i + 1) * m + j);if(j + 1 < m && src[i][j + 1] != '#')Add(i * m + j,i * m + j + 1);}for(int i = 0; i < m * n; ++i)if(!dfn[i])Tarjan(i);for(int x = 0; x < m * n; ++x)for(int i = head[x]; i; i = next[i])if(changed[x] != changed[aim[i]])_Add(changed[x],changed[aim[i]]);SPFA();int *ans = max_element(f + 1,f + scc + 1);printf("%d\n",*ans);}return 0;}
Poj 3592 instantaneous transference Tarjan + spfa