现在的位置: 首页 > 综合 > 正文

POJ 3592 Instantaneous Transference(建图+缩点)

2018年04月22日 ⁄ 综合 ⁄ 共 2090字 ⁄ 字号 评论关闭

题意:在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;
}

抱歉!评论已关闭.