题意:

  给一个矩形,矩形中某些点有一定数量的矿石,有些点为传送点,有些点为障碍。你驾驶采矿车(ore-miner truck,我也不知道是什么),从左上角出发,采尽量多的矿石,矿石不可再生。不能往左边或者上面走。传送点可以往左边或上面传。2<=n,m<=40

分析:

  可以把矩形看作一张图,每个格子为一个点,每个格子与它右边和下面的点连接一条有向边。每个传送点与它传送的位置连接一条有向边。如果右边或下面为#那么不连。值得注意的是题目并没有保证传送点传送到的一定不是#,所以需要进行判断。

   这样,我们得到了一个点数|V|=n*m,边数最大|E|=O(n*m)的有向有环图。答案就是限制只能取一次的最长路。

  我们现在的任务就是把只能取一次抽象成另一种能实现的东西,不然暴力是指数级的。

  很显然,向后传送不需要考虑,只考虑传回前面,在图上的表现为成环,或者说同属一个强连通分量。

  很自然地就可以发现同属一个强连通分量的点都可以同时取到,我们考虑用tarjan缩点,这样建的就是一个DAG,在这个DAG上跑最长路,就是答案。

   这里值得一提的是,这里不能用dijkstra,同时我们可以下结论:求最长路时,dijkstra算法只适用于负权图,求最短路时,dijkstra算法只适用于正权图。所以这里要写SPFA。

代码:用emacs写的,所以不要吐槽两格缩进

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<cstring>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
int low[],dfn[],arr[],scc[],al,cl,w[];
vector<int> g[];
vector<int> ng[];
stack <int> sta;
void tarjan(int now){
low[now]=dfn[now]=++cl;
sta.push(now);
for(int i=;i<g[now].size();i++){
int k=g[now][i];
if(arr[k])continue;
if(!dfn[k]){
tarjan(k);
low[now]=min(low[now],low[k]);
}else
low[now]=min(low[now],dfn[k]);
}
if(low[now]==dfn[now]){
al++;
while(){
int u=sta.top();
sta.pop();
arr[u]=;
scc[u]=al;
if(u==now) break;
}
}
}
int a[][];
void readint(int n,int m){
memset(arr,,sizeof(arr));
memset(w,,sizeof(w));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(scc,,sizeof(scc));
al=cl=;
for(int i=;i<=n*m;i++)g[i].clear(),ng[i].clear();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
char x;cin>>x;
if(x=='*')a[i][j]=;
else
if(x=='#')a[i][j]=-;
else a[i][j]=(int)(x-);
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(j+<=m&&a[i][j+]!=-)g[i*m-m+j].push_back(i*m-m+j+);
if(i+<=n&&a[i+][j]!=-)g[i*m-m+j].push_back(i*m+j);
if(a[i][j]==){
int x,y;cin>>x>>y;
if(a[x+][y+]==-)continue;
else g[i*m-m+j].push_back(x*m+y+);
}
}
}
}
void dij(int n){//SPFA找最长路
queue <int> que;
int dist[];
memset(dist,,sizeof(dist));
dist[scc[]]=w[scc[]];
que.push(scc[]);
while(!que.empty()){
int k=que.front();
for(int i=;i<ng[k].size();i++){
if(dist[k]+w[ng[k][i]]>dist[ng[k][i]]){
dist[ng[k][i]]=dist[k]+w[ng[k][i]];
que.push(ng[k][i]);
}
}
que.pop();
}
int maxx=;
for(int i=;i<=n;i++)maxx=max(maxx,dist[i]);
cout<<maxx<<endl;
} int main(){
int t;cin >> t;
while(t--){
int n,m;
cin>>n>>m;
readint(n,m);
for(int i=;i<=n*m;i++)
if(!arr[i])
tarjan(i);//求强连通分量
for(int i=;i<=n*m;i++){
for(int j=;j<g[i].size();j++){
if(scc[i]==scc[g[i][j]])continue;
ng[scc[i]].push_back(scc[g[i][j]]);
}
}//缩点
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(a[i][j]==-||a[i][j]==)continue;
w[scc[i*m-m+j]]+=a[i][j];
}
}//算新的点权
dij(al);//求最长路
}
return ;
111 }

  

POJ3592 Instantaneous Transference题解的更多相关文章

  1. POJ3592 Instantaneous Transference 强连通+最长路

    题目链接: id=3592">poj3592 题意: 给出一幅n X m的二维地图,每一个格子可能是矿区,障碍,或者传送点 用不同的字符表示: 有一辆矿车从地图的左上角(0,0)出发, ...

  2. POJ3592 Instantaneous Transference tarjan +spfa

    链接:http://poj.org/problem?id=3592 题意:题目大意:给定一个矩阵,西南角为出发点,每个单位都有一订价值的金矿(#默示岩石,不成达,*默示时佛门,可以达到指定单位),队# ...

  3. poj3592 Instantaneous Transference tarjan缩点+建图

    //给一个n*m的地图.坦克从(0 , 0)開始走 //#表示墙不能走,*表示传送门能够传送到指定地方,能够选择也能够选择不传送 //数字表示该格的矿石数, //坦克从(0,0)開始走.仅仅能往右和往 ...

  4. poj 3592 Instantaneous Transference 【SCC +缩点 + SPFA】

    Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6204   Accep ...

  5. POJ 3592 Instantaneous Transference(强连通+DP)

    POJ 3592 Instantaneous Transference 题目链接 题意:一个图.能往右和下走,然后有*能够传送到一个位置.'#'不能走.走过一个点能够获得该点上面的数字值,问最大能获得 ...

  6. POJ 3592 Instantaneous Transference(强联通分量 Tarjan)

    http://poj.org/problem?id=3592 题意 :给你一个n*m的矩阵,每个位置上都有一个字符,如果是数字代表这个地方有该数量的金矿,如果是*代表这个地方有传送带并且没有金矿,可以 ...

  7. poj 3592 Instantaneous Transference

    http://poj.org/problem?id=3592 #include <cstdio> #include <cstring> #include <algorit ...

  8. poj 3592 Instantaneous Transference 缩点+最长路

    题目链接 给一个n*m的图, 从0, 0这个点开始走,只能向右和向下. 图中有的格子有值, 求能获得的最大值. 其中有些格子可以传送到另外的格子, 有些格子不可以走. 将图中的每一个格子都看成一个点, ...

  9. Instantaneous Transference(强连通分量及其缩点)

    http://poj.org/problem?id=3592 题意:给出一个n*m的矩阵,左上角代表起始点,每个格子都有一定价值的金矿,其中‘#’代表岩石不可达,‘*’代表时空门可以到达指定格子,求出 ...

随机推荐

  1. Linux配置JDK

    在etc/profile文件下添加 export JAVA_HOME=/root/Desktop/jdk1.7.0_79 export CLASSPATH=/root/Desktop/jdk1.7.0 ...

  2. if(){}else 语句的正确写法以及它的嵌套使用

    if(一个返回bool值的条件表达式) { 程序块 } else{} 它的执行过程我们可以通过一个程序来了解 static void Main(string[] args) { ) // 条件1 { ...

  3. 《深入理解Java虚拟机》学习笔记之最后总结

    编译器 Java是编译型语言,按照编译的时期不同,编译器可分为: 前端编译器:其实叫编译器的前端更合适些,它把*.java文件转变成*.class文件,如Sun的Javac.Eclipse JDT中的 ...

  4. 《深入理解Java虚拟机》学习笔记之内存分配

    JVM在执行Java程序的过程中会把它所管理的内存划分若干个不同的数据区域,如下图: 大致可以分为两类:线程私有区域和线程共享区域. 线程私有区域 程序计数器(Program Counter Regi ...

  5. 算法模板——splay区间反转 2

    实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...

  6. AVFoundation自定义录制视频

    #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface ...

  7. Java 反射的理解

    反射反射,程序员的快乐,今天你快乐了吗?如果你不快乐,没关系,接下来让你快乐起来! 一.什么是反射? 通过百度百科我们可以知道,Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  8. .NET客户端实现Redis中的管道(PipeLine)与事物(Transactions)

    序言 Redis中的管道(PipeLine)特性:简述一下就是,Redis如何从客户端一次发送多个命令,服务端到客户端如何一次性响应多个命令. Redis使用的是客户端-服务器模型和请求/响应协议的T ...

  9. RabbitMQ-从基础到实战(2)— 防止消息丢失

    转载请注明出处 1.简介 RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失.针对这两种消息丢失,RabbitMQ都给出了相应的解决方案. 2.防止客户端丢失消息 如图,生产者P向 ...

  10. java基础之基础语法详录(一)

    [前言] java的语法先从基础语法学,Java语言是由类和对象组成的,其对象和类又是由方法和变量组成,而方法,又包含了语句和表达式. 对象:(几乎)一切都是对象,比如:一只熊猫,他的外观,颜色,他在 ...