首页 > 代码库 > POJ 3592 Instantaneous Transference Tarjan+SPFA
POJ 3592 Instantaneous Transference Tarjan+SPFA
题目大意:给出一张地图,有数字的点代表上面有数字个矿物,*代表这个点可以传送到另一个点上,#代表不能走。从一个点只能到这个点的下方和右方。现在从(0,0)开始,问最多可以收集多少矿物。
思路:这个题肯定是建图,然后最长路,关键是有了传送,就有可能形成正权环,然后在SPFA的过程中就会死循环。一个环上的所有权值只能得到一次,所以就用一次Tarjan求出所有的环,把权值累计一下,变成一个点,然后重新建图。这样得到的图就是拓扑图了,没有环,可以无忧无虑的SPFA了。
PS:这个题我用拓扑排序怎么也切不了,求大神告知这是为什么!!!
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 20010 using 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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。