题意:在n*m 的图上只能向右4和向下走,问最多可以那都拿走多少矿石;# 表示不能到达该点,*表示该点可以传送的其他的点。
该图是一个有向图,可以传送到前面的点,所以可能出现环,因此可以用联通图缩点。然后从(0,0)点开始找最长的路劲。
做这题出现了各种错,无语了。
一组数据:
1
4 4
111*
1121
1*11
1111
2 0
0 2
答案:10
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int N = 49;
const int M = 1609;
int n,m;
char map[N][N];
struct LT{
int to,nex;
} L[M<<2],NL[M<<2];
int F[M],cnt;
int NF[M],ncnt;
void add(int f,int t)
{
L[cnt].nex = F[f];
L[cnt].to = t;
F[f] = cnt++;
}
int val[M];
void init()
{
scanf("%d%d",&n,&m);
memset(F,0,sizeof(F)); cnt = 1;
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
for(int j=0;j<m;j++)
{
if(map[i][j]>='0'&&map[i][j]<='9')
val[i*m+j] = map[i][j] -'0';
else val[i*m+j] = 0;
if(map[i][j]=='#') continue;
if(i>0&&map[i-1][j]!='#') add((i-1)*m+j,i*m+j);
if(j>0&&map[i][j-1]!='#') add(i*m+j-1,i*m+j);
}
}
int x,y;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(map[i][j]=='*')
{
scanf("%d%d",&x,&y);
add(i*m+j,x*m+y);
}
}
int dfn[M],low[M],col[M],color,ind;
bool post[M];
stack<int> S;
void tdfs(int k)
{
low[k] = dfn[k] = ind++;
post[k] = true;S.push(k);
for(int i=F[k];i;i=L[i].nex)
{
int to = L[i].to;
if(!dfn[to])
{
tdfs(to);
low[k] = min(low[k],low[to]);
}else if(post[to]&&low[k]>dfn[to])
low[k] = dfn[to];
}
if(low[k]==dfn[k])
{
color++;int i;
for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop())
{
col[i] = color;post[i] = false;
}
col[k] = color;post[k] = false;
}
}
void tarjan()
{
for(int i=0;i<(n*m);i++) dfn[i] = low[i] = 0,post[i] = false;
ind = 1,color=0;while(!S.empty())S.pop(); tdfs(0);
}
int nval[M];
void nadd(int f,int t)
{
NL[ncnt].nex = NF[f];
NL[ncnt].to = t;
NF[f] = ncnt++;
}
int dp[M],ans;
int visit[M];
void dfs(int k,int s)
{
if(visit[k]) return ;
s+=nval[k];
if(dp[k]>s) return ;
visit[k] = true;
dp[k] = s;
ans = max(ans,s);
for(int i=NF[k];i;i=NL[i].nex)
{
int to = NL[i].to;
dfs(to,s);
}
visit[k] = false;
}
void solve()
{
memset(col,0,sizeof(col));
tarjan();
memset(NF,0,sizeof(NF));ncnt = 1;
memset(nval,0,sizeof(nval));
for(int i=0;i<(n*m);i++)
{
nval[col[i]] += val[i];
for(int j=F[i];j;j=L[j].nex)
{
int to = L[j].to;
nadd(col[i],col[to]);
}
}
ans = 0;
memset(dp,0,sizeof(dp));
memset(visit,false,sizeof(visit));
dfs(col[0],0);
printf("%d\n",ans);
}
int main()
{
freopen("in.txt","r",stdin);
int cas;
scanf("%d",&cas);
while(cas--)
{
init();
solve();
}
return 0;
}