题意:

  给一个矩形,矩形中某些点有一定数量的矿石,有些点为传送点,有些点为障碍。你驾驶采矿车(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. 前端学PHP之正则表达式基础语法

    前面的话 正则表达式是用于描述字符排列和匹配模式的一种语法规则.它主要用于字符串的模式分割.匹配.查找及替换操作.在PHP中,正则表达式一般是由正规字符和一些特殊字符(类似于通配符)联合构成的一个文本 ...

  2. ABP Zero 单部署,单数据库,多租户架构

    首先,我们应该定义多租户系统中的两个条目: 租主(Host):租主是单例的(只有一个租主).租主会对创建和管理租户负责.因此,一个“租主用户”比所有的租户等级更高,并独立于所有租户,同时还能控制他们. ...

  3. Sublime Text 3 (Build 3126) 最新注册码

    Sublime Text 作为程序员开发神器,听说最新版更新了 并且增加了不少新特性.马上到官网下载了最新版 Sublime Text 3 3126 使用了下,反应速度比以前的确更快了.随手找了几个S ...

  4. Lambda表达式和Java集合框架

    本文github地址 前言 我们先从最熟悉的Java集合框架(Java Collections Framework, JCF)开始说起. 为引入Lambda表达式,Java8新增了java.util. ...

  5. input 即时搜索 监听输入值的变化

    在 Web 开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理 ...

  6. [HDOJ2572]终曲

    Problem Description 最后的挑战终于到了!站在yifenfei和MM面前的只剩下邪恶的大魔王lemon一人了!战胜他,yifenfei就能顺利救出MM.Yifenfei和魔王lemo ...

  7. 1934: [Shoi2007]Vote 善意的投票

    1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1174  Solved: 723[Submit][S ...

  8. HashSet和TreeSet 的区别与分析

    Set是java中一个不包含重复元素的collection.更正式地说,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素.正如其名称所暗示的, ...

  9. idea调试SpringMvc, 出现:”通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明“错误的解决方法

    调试json格式输出,出现以下错误: HTTP Status 500 - Servlet.init() for servlet HelloDispatcher threw exception   ty ...

  10. TFS2017代码搜索功能

    当团队或者公司的研发中心的代码库扩展到了一定程度,在代码库中查找一些需要的代码会变的比较困难.比如敏捷模式下的项目小组希望能够找到并重用其他小组开发的一些基础性的功能代码,我们通常需要去找当事人去询问 ...