poj 3592 Instantaneous Transference 缩点+最长路

题目链接

给一个n*m的图, 从0, 0这个点开始走,只能向右和向下。 图中有的格子有值, 求能获得的最大值。 其中有些格子可以传送到另外的格子, 有些格子不可以走。

将图中的每一个格子都看成一个点, 然后对它右边和下边的点连边, 如果是'#’就continue,  如果可以传送, 那么就对传送到的那个点连边, 同时也要向右边和下边连边, 因为可以选择不传送。 然后缩点求最长路就可以。

一个数组没有初始化RE了好多发.....

  1 #include <iostream>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <map>
  8 #include <set>
  9 #include <string>
 10 #include <queue>
 11 using namespace std;
 12 #define pb(x) push_back(x)
 13 #define ll long long
 14 #define mk(x, y) make_pair(x, y)
 15 #define lson l, m, rt<<1
 16 #define mem(a) memset(a, 0, sizeof(a))
 17 #define rson m+1, r, rt<<1|1
 18 #define mem1(a) memset(a, -1, sizeof(a))
 19 #define mem2(a) memset(a, 0x3f, sizeof(a))
 20 #define rep(i, a, n) for(int i = a; i<n; i++)
 21 #define ull unsigned long long
 22 typedef pair<int, int> pll;
 23 const double PI = acos(-1.0);
 24 const double eps = 1e-8;
 25 const int mod = 1e9+7;
 26 const int inf = 1061109567;
 27 const int dir[][2] = { {1, 0}, {0, 1}, {0, -1}, {0, 1} };
 28 const int maxn = 2000;
 29 const int maxE = 1e5+5;
 30 int num, val[maxn], n, m, low[maxn], dfn[maxn], s[maxn], instack[maxn], st[maxn], top, cnt, cnum;
 31 int sumval[maxn], head2[maxE], head[maxE], dis[maxn];
 32 char g[45][45];
 33 struct node
 34 {
 35     int to, nextt;
 36 }e[maxE], e2[maxE];
 37 int dfs(int u) {
 38     if(~dis[u])
 39         return dis[u];
 40     int ans = sumval[u], ret = 0;
 41     for(int i = head2[u]; ~i; i = e2[i].nextt) {
 42         int v = e2[i].to;
 43         ret = max(ret, dfs(v));
 44     }
 45     return dis[u] = ret+ans;
 46 }
 47 void add2(int u, int v) {
 48     e2[num].to = v;
 49     e2[num].nextt = head2[u];
 50     head2[u] = num++;
 51 }
 52 void rebuild() {
 53     num = 0;
 54     for(int i = 0; i<n*m; i++) {
 55         int u = s[i];
 56         for(int j = head[i]; ~j; j = e[j].nextt) {
 57             int v = e[j].to;
 58             if(s[v] == u)
 59                 continue;
 60             add2(u, s[v]);
 61         }
 62     }
 63 }
 64 void tarjan(int u) {
 65     instack[u] = 1;
 66     st[top++] = u;
 67     dfn[u] = low[u] = ++cnt;
 68     for(int i = head[u]; ~i; i = e[i].nextt) {
 69         int v = e[i].to;
 70         if(!dfn[v]) {
 71             tarjan(v);
 72             low[u] = min(low[v], low[u]);
 73         } else if(instack[v]) {
 74             low[u] = min(low[u], dfn[v]);
 75         }
 76     }
 77     if(low[u] == dfn[u]) {
 78         ++cnum;
 79         int x;
 80         do {
 81             x = st[--top];
 82             instack[x] = 0;
 83             s[x] = cnum;
 84             sumval[cnum] += val[x];
 85         } while( x!=u );
 86     }
 87 }
 88 int judge(int x, int y) {
 89     if(x>=0&&x<n&&y>=0&&y<m&&g[x][y]!='#')
 90         return 1;
 91     return 0;
 92 }
 93 void add(int u, int v) {
 94     e[num].to = v;
 95     e[num].nextt = head[u];
 96     head[u] = num++;
 97 }
 98 void build()
 99 {
100     scanf("%d%d", &n, &m);
101     for(int i = 0; i<n; i++)
102         scanf("%s", g[i]);
103     int x, y;
104     for(int i = 0; i<n; i++) {
105         for(int j = 0; j<m; j++) {
106             if(g[i][j] == '#')
107                 continue;
108             if(g[i][j] == '*') {
109                 scanf("%d%d", &x, &y);
110                 add(i*m+j, x*m+y);
111             }
112             if(g[i][j]!='*')
113                 val[i*m+j] = g[i][j]-'0';
114             for(int k = 0; k<2; k++) {
115                 int tmpx = i+dir[k][0];
116                 int tmpy = j+dir[k][1];
117                 if(judge(tmpx, tmpy))
118                     add(i*m+j, tmpx*m+tmpy);
119             }
120         }
121     }
122 }
123 void init() {
124     num = top = cnum = cnt = 0;
125     mem(dfn);
126     mem(sumval);
127     mem1(head);
128     mem1(head2);
129     mem1(dis);
130     mem(instack);
131     mem(low);
132     mem(val);
133     mem(s);
134 }
135 int main()
136 {
137     int t, ans;
138     cin>>t;
139     while(t--) {
140         init();
141         build();                 //建图
142         tarjan(0);               //缩点
143         rebuild();               //对缩点后的图建图
144         ans = dfs(s[0]);         //记忆化搜索求最长路
145         cout<<ans<<endl;
146     }
147     return 0;
148 }
原文地址:https://www.cnblogs.com/yohaha/p/5056427.html