天天看点

POJ 3592 Instantaneous TransferencePOJ 3592 Instantaneous Transference

POJ 3592 Instantaneous Transference

targan,spfa

传送门:HustOJ

传送门:POJ

题意

一个N*M的矩阵,矩阵内每点可能是数字1~9:表示这点有数字个矿石,可能是*,表示这点是个超时空传送点,矩阵结束后按顺序给出传送点的传送目的地坐标,可能是#:表示该点不可达。

任何矿石点可以到达其右侧点或下侧点,只要右或下点不是#;传送点也可以到其右或下,只要右或下点不是#。

现在矿车在(0,0),问矿车走一趟最多可以采多少矿。

思路

思路很简单,有向图先缩点变成DAG,每个连通分量内矿石一定全部可以采到,然后相当于DAG最长路。

矩阵每个点视作图中一点,按可达关系建边,保存每点的矿石数量。矩阵中(i,j)在图中编号i*m+j,m是一行的点数。传送点和不可达点的矿石数是0。建图后targar缩点,顺便求出每个新点(连通块)的矿石总数。按连通块编号建新图,跑SPFA。

细节挺多,coding时多加注意。

代码

#include <cstdio>
#include <cstdlib>
//#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>

//#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=*;
const int oo=;
typedef long long LL;
const LL loo=l;
typedef long double LB;
const LL mod=+;

int sumval[MAXN];
int val[MAXN];
int tra[MAXN];
char mp[][];

struct Targan
{
    vector<int> G[MAXN];
    int pre[MAXN], lowlink[MAXN], sccno[MAXN], dfs_clock, scc_cnt;
    stack<int> S;
    void init()
    {
        for(int i=;i<MAXN;i++) G[i].clear();
        while(!S.empty()) S.pop();
    }
    void addedge(int a, int b) { G[a].push_back(b); }
    void dfs(int u)
    {
        pre[u]=lowlink[u]=++dfs_clock;
        S.push(u);
        for(int i=;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(!pre[v])
            {
                dfs(v);
                lowlink[u]=min(lowlink[u], lowlink[v]);
            }
            else if(!sccno[v])
            {
                lowlink[u]=min(lowlink[u], pre[v]);
            }
        }
        if(lowlink[u]==pre[u])
        {
            scc_cnt++;
            while()
            {
                int x=S.top();S.pop();
                sccno[x]=scc_cnt;
                sumval[scc_cnt]+=val[x];
                if(x==u) break;
            }
        }
    }
    void find_scc(int n)
    {
        dfs_clock=scc_cnt=;
        M(sccno, );M(pre, );
        for(int i=;i<n;i++)
            if(!pre[i])
                dfs(i);
    }
}targan;
struct Spfa
{
    vector<int>G[MAXN];
    int dis[MAXN], vis[MAXN];
    void init()
    {
        for(int i=;i<MAXN;i++) G[i].clear();
    }
    void addedge(int a, int b)
    {
        G[a].push_back(b);
    }
    void diy()
    {
        M(dis, );M(vis, );
        queue<int> que;
        que.push(targan.sccno[]);
        vis[targan.sccno[]]=;
        dis[targan.sccno[]]=sumval[targan.sccno[]];

        while(!que.empty())
        {
            int u=que.front();que.pop();vis[u]=;
            for(int i=;i<G[u].size();i++)
            {
                int v=G[u][i];
                if(dis[u]+sumval[v]>dis[v])
                {
                    dis[v]=dis[u]+sumval[v];
                    if(!vis[v])
                    {
                        que.push(v);
                        vis[v]=;
                    }
                }
            }
        }
    }
}spfa;

int main()
{
    //_;
    int T;scanf("%d", &T);
    while(T--)
    {
        targan.init();
        M(val, );M(mp, );M(tra, );M(sumval, );

        int n, m;scanf("%d%d", &n, &m);
        int trans=;
        for(int i=;i<n;i++) scanf("%s", mp[i]);
        for(int i=;i<n;i++)
        {
            for(int j=;j<m;j++)
            {
                if(mp[i][j]=='#') continue;
                else if(mp[i][j]=='*')
                {
                    int a, b;scanf("%d%d", &a, &b);

                    targan.addedge(i*m+j, a*m+b);
                    if(i+<n && mp[i+][j]!='#')
                        targan.addedge(i*m+j, (i+)*m+j);
                    if(j+<m && mp[i][j+]!='#')
                        targan.addedge(i*m+j, i*m+j+);
                }
                else
                {
                    int nnn=mp[i][j]-'0';
                    val[i*m+j]=nnn;
                    if(i+<n && mp[i+][j]!='#')
                        targan.addedge(i*m+j, (i+)*m+j);
                    if(j+<m && mp[i][j+]!='#')
                        targan.addedge(i*m+j, i*m+j+);
                }
            }
        }

        int v=n*m;
        targan.find_scc(v);
        spfa.init();

        for(int i=;i<v;i++)
        {
            for(int j=;j<targan.G[i].size();j++)
            {
                if(targan.sccno[i]!=targan.sccno[targan.G[i][j]])
                {
                    spfa.addedge(targan.sccno[i], targan.sccno[targan.G[i][j]]);
                }
            }
        }
        spfa.diy();
        int res=;
        for(int i=;i<=targan.scc_cnt;i++)
        {
            res=max(res, spfa.dis[i]);
        }
        printf("%d\n", res);
    }
    return ;
}