给一个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 }