//给一个n*m的地图。坦克从(0 , 0)開始走
//#表示墙不能走,*表示传送门能够传送到指定地方,能够选择也能够选择不传送
//数字表示该格的矿石数,
//坦克从(0,0)開始走。仅仅能往右和往下走。
//问最多能得到多少矿石
//直接建图,但因为有传送门。须要缩点
//然后用dfs直接搜一条权值最大的路
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
using namespace std ;
const int maxn = 2010 ;
int dfn[maxn] , low[maxn] , vis[maxn] , stack[maxn] ;int ans ;
int head[maxn*maxn] , belong[maxn] ,isstack[maxn] ;
int num , top , nedge , step ;int X[maxn] , Y[maxn] ; int n, m ;
int w[maxn];int a[maxn];int len;int visit[50][50];
int map[maxn][maxn] ;int pos ;
char str[maxn][maxn] ;
int dx[2] = {0,1} ;
int dy[2] = {1,0} ;
vector<int>vec[maxn] ;
struct Edge
{
int v ;
int next ;
}edge[maxn*maxn] ;
void addedge(int u , int v)
{
edge[nedge].v = v ;
edge[nedge].next = head[u] ;
head[u] = nedge++ ;
}
void init()
{
for(int i = 0;i <= n*m;i++)
vec[i].clear() ;
memset(head , -1 , sizeof(head)) ;
memset(w ,0 , sizeof(w)) ;
memset(dfn , 0 , sizeof(dfn)) ;
memset(isstack ,0 , sizeof(isstack)) ;
memset(map , 0 , sizeof(map)) ;
memset(vis ,0 , sizeof(vis)) ;
memset(a ,0 , sizeof(a)) ;
num = top = nedge = step = len = 0 ;
}
void tarjan(int u)
{
stack[++top] = u ;
isstack[u] = 1 ;
low[u] = dfn[u] = ++step ;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v ;
if(!dfn[v])
{
tarjan(v) ;
low[u] = min(low[u] , low[v]) ;
}
else if(isstack[v])
low[u] = min(low[u] , dfn[v]) ;
}
if(low[u] == dfn[u])
{
num++ ;
int v = -1 ;
while(u != v)
{
v = stack[top--] ;
isstack[v] = 0 ;
belong[v] = num ;
w[num] += a[v];
if(v==0)pos = num ;
}
}
}
void build_tree()
{
for(int i = 0;i <= n*m;i++)
for(int j = head[i] ; j != -1 ; j =edge[j].next)
{
int u = belong[i] ;
int v = belong[edge[j].v] ;
if(u == v)continue ;
vec[u].push_back(v) ;
vis[v] = 1 ;
}
}
int dfs(int u)
{
int ma = 0 ;
for(int i = 0;i < vec[u].size() ;i++)
{
int v = vec[u][i] ;
ma = max(ma , dfs(v)) ;
}
ans = max(ans , ma+w[u]) ;
return ma + w[u] ;
}
int main()
{
//freopen("in.txt" , "r" , stdin) ;
int t ;
scanf("%d" , &t) ;
while(t--)
{
scanf("%d%d" , &n , &m) ;
init() ;
ans = 0 ;
for(int i = 0;i < n;i++)
scanf("%s" ,str[i]) ;
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
if(str[i][j] != '#')
{
if(str[i][j] == '*')
{
X[++len] = i ;
Y[len] = j ;
a[i*m+j] = 0 ;
}
else
{
a[i*m + j] = str[i][j] - '0' ;
ans = max(ans , a[i*m+j]) ;
}
for(int k = 0 ;k < 2;k++)
{
int nx = i + dx[k] ;
int ny = j + dy[k] ;
if((nx >= n || ny >= m))
addedge(i*m + j , n*m) ;
else if(str[nx][ny] != '#')
addedge(i*m + j , nx*m + ny) ;
}
}
}
for(int i = 1;i <= len ;i++)
{
int u , v ;
scanf("%d%d" , &u , &v) ;
addedge(X[i]*m+ Y[i] , u*m+v) ;
}
pos = 0 ;
for(int i = 0;i <= n*m;i++)
if(head[i] != -1 && !dfn[i])
tarjan(i) ;
if(!pos)
{
cout<<ans<<endl;
continue ;
}
build_tree() ;
dfs(pos) ;
printf("%d\n" ,ans) ;
}
}

poj3592 Instantaneous Transference tarjan缩点+建图的更多相关文章

  1. poj2186Popular Cows+tarjan缩点+建图

    传送门: 题意: 给出m条关系,表示n个牛中的崇拜关系,这些关系满足传递性.问被所有牛崇拜的牛有几头: 思路: 先利用tarjan缩点,同一个点中的牛肯定就是等价的了,建立新的图,找出其中出度为0的点 ...

  2. POJ3592 Instantaneous Transference tarjan +spfa

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

  3. 炸弹:线段树优化建边+tarjan缩点+建反边+跑拓扑

    这道题我做了有半个月了...终于A了... 有图为证 一句话题解:二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案 首先我们根据题意,判断出来要炸弹可以连着炸,就是这个炸弹能炸到的可以 ...

  4. HDU 1045 Fire Net(行列匹配变形+缩点建图)

    题意:n*n的棋盘上放置房子.同一方同一列不能有两个,除非他们之间被墙隔开,这种话. 把原始图分别按行和列缩点 建图:横竖分区.先看每一列.同一列相连的空地同一时候看成一个点,显然这种区域不可以同一时 ...

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

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

  6. hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  7. POJ3592 Instantaneous Transference题解

    题意: 给一个矩形,矩形中某些点有一定数量的矿石,有些点为传送点,有些点为障碍.你驾驶采矿车(ore-miner truck,我也不知道是什么),从左上角出发,采尽量多的矿石,矿石不可再生.不能往左边 ...

  8. Tarjan缩点+DAG图dp

    题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...

  9. We Need More Bosses CodeForces - 1000E(缩点 建图 求桥 求直径)

    题意: 就是求桥最多的一条路 解析: 先求连通分量的个数 然后缩点建图  求直径即可 #include <bits/stdc++.h> #define mem(a, b) memset(a ...

随机推荐

  1. ZIP排除指定目录进行压缩

    zip -r glog-0.3.5.zip glog-0.3.5/  -x "glog-0.3.5/doc/*" unzip -v glog-0.3.5.zip 进行查看ZIP的内 ...

  2. sql中where和having的区别

    “Where” 是一个约束声明,使用Where来约束来自数据库的数据,Where是在结果返回之前起作用的,且Where中不能使用聚合函数. “Having”是一个过滤声明,是在查询返回结果集以后对查询 ...

  3. C++使用第三方静态库的方法

    以jasoncpp为例 首先在github下载最新的的jasoncpp包并解压 找到类似makefiles的文件编译,一般是打开sln文件使用vs编译(生成解决方案),在build文件中可以找到对应的 ...

  4. OpenStack 存储服务 Cinder存储节点部署LVM (十四)

    部署在block(10.0.0.103)主机 一)配置lvm 1.安装lvm2软件包 yum install lvm2 -y 2.启动LVM的metadata服务并且设置该服务随系统启动 system ...

  5. Bootstrap Table相关参数及属性、方法

    http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/#%E4%BA%8B%E4%BB%B6

  6. [BZOJ2669][CQOI2012]局部最小值(容斥+状压DP)

    发现最多有8个限制位置,可以以此为基础DP和容斥. $f_{i,j}=f_{i-1,j}\times (cnt_j-i+1)+\sum_{k\subset j} f_{i-1,k}$ $cnt_j$表 ...

  7. 【树状数组逆序对】USACO.2011JAN-Above the median

    [题意] 给出一串数字,问中位数大于等于X的连续子串有几个.(这里如果有偶数个数,定义为偏大的那一个而非中间取平均) [思路] 下面的数据规模也小于原题,所以要改成__int64才行.没找到测试数据, ...

  8. XMPP聊天之Openfire 的安装和配置---Mac OS

    一.下载并安装openfire 1.下载最新的openfire安装文件 官方下载站点:http://www.igniterealtime.org/downloads/index.jsp#openfir ...

  9. [SimpleOJ239]Cards

    题目大意: 有n(n为偶数)张牌,每张牌正反面有两张数字,你可以从中选出n/2张牌,减去某一面的数字,再选出另外n/2张牌,加上某一面的数字,问最终的答案最小能是多少? 思路: 先不考虑n/2的限制, ...

  10. python基础之条件判断和循环

    1.条件判断 age = 3 if age >= 18: print('adult') elif age >= 6: print('teenager') else: print('kid' ...