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

poj 3592 Instantaneous Transference

2018年01月11日 ⁄ 综合 ⁄ 共 2600字 ⁄ 字号 评论关闭


这道题的题意为:

给你一个n*m的地图 这个地图中有三种格式 

第一种 '*' 代表这个地方可以使用魔法跳转到另一个地方(后面告诉)。

第二种 ‘0’~‘9’
代表这个地方可以得到的矿石数量。

第三种 ‘#’  
代表这个地方是墙 不能通过。

然后再给你每一个'*'可以跳转到的地方 从左到右 从上到下 一次给出

起点为 左上角 每一个方格 可以向下或者向右走 

然后让你求 这个地图中 最多能得到多少矿石(起点为左上角,终点任意)(魔法可以无限次用 但是 每个方格的矿石只能得到一次)

输出这个答案。



我的做法:

spfa+缩点 缩点可以用tarjan强连通算法

如果可以施展魔法跳到另一个的地方之后。 如果能从那个地方再回到这个地方。那么所有这条路径上的点权都可以缩为1点。它形成了一个环 可以通过tarjan求出强连通分量 然后以这些强连通分量建图跑一遍spfa就可以得出答案。。详情代码。 


//author: CHC
//First Edit Time:	2014-06-10 19:33
//Filename:D:\bc\做题\图论训练\强连通\poj 3592 Instantaneous Transference\1.cpp
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
char map1[50][50];
int map2[50][50];
int val[2500];
int dis[2500];
struct point {
    int x,y,tx,ty;
}cs[2500];
#define MAXN 2500
vector <int> e1[MAXN];
vector <int> e[MAXN];
int dfn[MAXN],low[MAXN],stack[MAXN],bleg[MAXN];
int top,times,tot;
void tarjan_x(int u){
    dfn[u]=low[u]=++times;
    stack[++top]=u;
    for(int i=0;i<(int)e[u].size();i++){
        int v=e[u][i];
        if(!dfn[v]){
            tarjan_x(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!bleg[v])
            low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u]){
        bleg[0]++;
        do{
            bleg[stack[top]]=bleg[0];
        }while(stack[top--]!=u);
    }
}
void init(){
    memset(dfn,0,sizeof(dfn));
    memset(bleg,0,sizeof(bleg));
    top=times=0;
}
void tarjan(){
    init();
    //编号从1开始
    for(int i=1;i<=tot;i++)
        if(!dfn[i])tarjan_x(i);
}
int bfs(){
    queue <int> q;
    q.push(bleg[1]);
    memset(dis,0,sizeof(dis));
    dis[bleg[1]]=val[bleg[1]];
    int mm=0;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        if((mm<dis[now]))mm=dis[now];
        for(int i=0;i<(int)e1[now].size();i++){
            int next=e1[now][i];
            if(dis[now]+val[next]>dis[next]){
                dis[next]=dis[now]+val[next];
                q.push(next);
            }
        }
    }
    return mm;
}
int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<MAXN;i++)e[i].clear();
        for(int i=0;i<MAXN;i++)e1[i].clear();
        memset(val,0,sizeof(val));
        int tt=0;
        for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            scanf(" %c",&map1[i][j]);
            if (map1[i][j]=='#') {
                map2[i][j]=-1;
            }
            else if(map1[i][j]=='*'){
                map2[i][j]=0;
                cs[tt].x=i;
                cs[tt].y=j;
                ++tt;
            }
            else {
                map2[i][j]=map1[i][j]-'0';
            }
        }
        }
        for(int i=0;i<tt;i++){
            scanf("%d%d",&cs[i].tx,&cs[i].ty);
        }
        for(int i=0;i<tt;i++){
            int now=cs[i].x*m+cs[i].y+1;
            int next=cs[i].tx*m+cs[i].ty+1;
            e[now].push_back(next);
        }
        for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(map2[i][j]==-1){ continue; }
            int now=i*m+j+1;
            if(i+1<n&&map2[i+1][j]!=-1){
                int next=(i+1)*m+j+1;
                e[now].push_back(next);
            }
            if(j+1<m&&map2[i][j+1]!=-1){
                int next=i*m+j+1+1;
                e[now].push_back(next);
            }
        }
        }
        tot=n*m;
        tarjan();
        for(int i=1;i<=tot;i++){
            val[bleg[i]]+=map2[(i-1)/m][(i-1)%m];
            for(int j=0;j<(int)e[i].size();j++){
                int v=e[i][j];
                if(bleg[i]!=bleg[v]){
                    e1[bleg[i]].push_back(bleg[v]);
                }
            }
        }
        //printf("here\n");
        printf("%d\n",bfs());
    }
    return 0;
}


抱歉!评论已关闭.