http://poj.org/problem?id=3592

题意 :给你一个n*m的矩阵,每个位置上都有一个字符,如果是数字代表这个地方有该数量的金矿,如果是*代表这个地方有传送带并且没有金矿,可以传送到指定的位置,如果是#代表该位置不可走,初始位置在左上角,只能向下或向右走,并且走到传送带的时候可选择是否传送。问当走出去的时候能获得的最大近况数是多少。

思路 :先将二维矩阵转化成一维的点建图,可以向下向右建图,而且传送带也可以建边,缩点之后再建边,最后用spfa求最长路。

#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h> using namespace std; const int maxn = ;
const int INF = - ; int belong[maxn],instack[maxn],dfn[maxn],low[maxn],g[maxn],map[maxn],c[maxn] ;
//belong[i]指的是i点所在的联通分量的编号。instack模拟的是栈,因为每个节点是要入栈的,来判断是否属于同一个分量
//dfn[i]为搜索i结点的次序编号,Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。
//g[i]是指将一个矩阵从0到n*m编号之后的,i点所在的那个位置的宝藏数,map[i]记录的是第i个传送带的位置
//c[i]记录的是第i个联通分量中宝藏的总数。
int cntt,cnt,top,bcc_clock,cntb,n,m,num ;
int head1[maxn] ,head[maxn];
char point[][] ;//输入的地图
int dis[maxn],coun[maxn],index ;
bool vis[maxn],flag[maxn] ;
int dire[][] = {{,},{,}} ; struct node
{
int u,v,w,next ;
} p[maxn] ,ch[maxn]; void addedge(int u,int v)
{
p[cnt].u = u ;
p[cnt].v = v ;
p[cnt].next = head[u] ;
head[u] = cnt++ ;
} void addnode(int u,int v,int w)
{
ch[cntt].u = u ;
ch[cntt].v = v ;
ch[cntt].w = w ;
ch[cntt].next = head1[u] ;
head1[u] = cntt++ ;
} void tarjan(int u)
{
vis[u] = true ;
dfn[u] = low[u] = ++bcc_clock ;
instack[++top] = u ;
for(int i = head[u] ; i+ ; i = p[i].next)
{
int v = p[i].v ;
if(!dfn[v])
{
tarjan(v) ;
low[u] = min(low[u],low[v]) ;
}
else if(vis[v])
low[u] = min(low[u],dfn[v]) ;
}
if(dfn[u] == low[u])
{
cntb++ ;
int v ;
do
{
v = instack[top--] ;
vis[v] = false ;
belong[v] = cntb ;
}
while(v != u) ;
}
} void Init()
{
memset(dfn,,sizeof(dfn)) ;
memset(low,,sizeof(low)) ;
memset(belong,,sizeof(belong)) ;
memset(c,,sizeof(c)) ;
memset(vis,,sizeof(vis)) ;
num = ;
memset(head,-,sizeof(head)) ;
memset(head1,-,sizeof(head1)) ;
cnt = ,top = ,cntb = ,bcc_clock = ,cntt = ;
} bool relax(int u,int v,int w)
{
if(dis[v] < dis[u] + w)
{
dis[v] = dis[u] + w ;
return true ;
}
return false ;
} bool spfa(int u)
{
memset(flag,false,sizeof(flag)) ;
memset(coun,,sizeof(coun)) ;
flag[u] = true ;
for(int i = ; i <= cntb ; i++)
dis[i] = INF ;
queue<int >Q ;
Q.push(u) ;
dis[u] = ;
while(!Q.empty ())
{
int st = Q.front() ;
Q.pop() ;
flag[st] = false ;
for(int i = head1[st] ; i+ ; i = ch[i].next)
{
if(relax(st,ch[i].v,ch[i].w) && !flag[ch[i].v])
{
if((++coun[ch[i].v]) > m*n) return false ;
Q.push(ch[i].v) ;
flag[ch[i].v] = true ;
}
}
}
index = ;
for(int i = ; i <= cntb ; i++)
index = max(index,dis[i]) ;
return true ;
}
int main()
{
int T ;
scanf("%d",&T) ;
while(T--)
{
scanf("%d %d",&n,&m) ;
int cnnt = ;//记录传送带的个数
Init() ;
getchar() ;
for(int i = ; i < n ; i++)
scanf("%s",point[i]) ;
for(int i = ; i < n ; i++)
{
for(int j = ; j < m ; j++)
{
int k = i*m+j ;
if(point[i][j] == '#')
{
g[k] = - ;
continue ;
}
else
{
if(point[i][j] == '*')
{
map[cnnt++] = k ;
g[k] = ;
}
else if(point[i][j] >= '' && point[i][j] <= '')
g[k] = point[i][j] - '' ;
for(int ii = ; ii < ; ii++)
{
int xx = i+dire[ii][] ;
int yy = j+dire[ii][] ;
if(xx < n && yy < m)
{
if(point[xx][yy] != '#')
addedge(k,xx*m+yy) ;
}
}
}
}
}
for(int i = ; i < cnnt ; i++)
{
int x,y ;
scanf("%d %d",&x,&y) ;
if(point[x][y] != '#')
addedge(map[i],x*m+y) ;
}
// Init() ;
for(int i = ; i < n*m ; i++)
if(!dfn[i]) tarjan(i) ;
for(int i = ; i < n*m ; i++)
c[belong[i]] += g[i] ;
addnode(,belong[],c[belong[]]);//缩点之后的建边
for(int i = ; i < n*m ; i++)
{
for(int j = head[i] ; j + ; j = p[j].next)
{
int v = p[j].v ;
if(belong[i] != belong[v])
{
addnode(belong[i],belong[v],c[belong[v]]) ;//两个点不属于同一个联通分量
}
}
}
spfa() ;//求最长路
printf("%d\n",index) ;
} return ;
}

POJ 3592 Instantaneous Transference(强联通分量 Tarjan)的更多相关文章

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

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

  2. POJ 2186 Popular Cows(强联通分量)

    题目链接:http://poj.org/problem?id=2186 题目大意:    每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种 ...

  3. POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

    题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认 ...

  4. 强联通分量-tarjan算法

    定义:在一张有向图中,两个点可以相互到达,则称这两个点强连通:一张有向图上任意两个点可以相互到达,则称这张图为强连通图:非强连通图有极大的强连通子图,成为强联通分量. 如图,{1},{6}分别是一个强 ...

  5. [vios1023]维多利亚的舞会3<强联通分量tarjan>

    题目链接:https://vijos.org/p/1023 最近在练强联通分量,当然学的是tarjan算法 而这一道题虽然打着难度为3,且是tarjan算法的裸题出没在vijos里面 但其实并不是纯粹 ...

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

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

  7. POJ 3114 Countries in War(强联通分量+Tarjan)

    题目链接 题意 : 给你两个城市让你求最短距离,如果两个城市位于同一强连通分量中那距离为0. 思路 :强连通分量缩点之后,求最短路.以前写过,总感觉记忆不深,这次自己敲完再写了一遍. #include ...

  8. poj 3592 Instantaneous Transference

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

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

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

随机推荐

  1. 基于ubuntu和windows连接

    对于ubuntu和centos安装软件是不一样的 对于ubuntu是  apt-get install  +软件名字 但是对于centos是 yum install +软件名字 所以ubunu远程连接 ...

  2. smarty实现缓存

    首先需要在mySmarty中添加配置信息,开启缓存,设置缓存文件存放目录,设置缓存时间缓存可以实现减少访问数据库,减轻数据库压力,访问一次数据库,形成静态页面,下次直接调用这个页面,也可以用nocac ...

  3. R cannot be resolved to a variable 解决办法

    Android开发过程中,碰到R cannot be resolved to a variable的报错信息,好像没有很确定的错误原因,一般来说,我总结出几个可能的解决方法,希望试过以后管用... 1 ...

  4. popen pclose 不等待命令执行完毕

    $handle = popen("start D:\\test.bat", "r"); //exec("start D:\\test.bat" ...

  5. [java学习笔记]java语言基础概述之标识符&关键字&注释&常量和变量

    一.标识符 在程序中自定义的一些名称 由26个英文字母的大小写,数字,_$组成 定义合法标识符的规则: 不能以数字开头 不能使用关键字 java严格区分大小写 注意:在起名字时,为了提高阅读性,必须得 ...

  6. redis 入门笔记(一)

    redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的web应用程序的完美解决方案 三个主要特点:      1,Redis数据库完全在内存中,使用磁盘仅用于持久性       ...

  7. 关于静态库和动态库的理解(C++)

    库的存在,是软件模块化的基础. 库存在的意义: } 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议.      } 现实中每个程序都要依赖很多基础的底层库,不可能每个人的 ...

  8. php socket connect permission denied

    Linux在php socket连接时报错:permission denied 解决办法: # setsebool httpd_can_network_connect=1 参考来源: http://w ...

  9. PHP — 用PHP实现一个双向队列

    1.简介 deque,全名double-ended queue,是一种具有队列和栈的性质的数据结构.双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行.双向队列(双端队列)就像是一个队 ...

  10. (转载)使用ADOConnet.BeginTrans后,出现错误提示:无法在此会话中启动更多的事务?

    Q: 三层结构,在服务器端使用adoconnection连接到sqlserver2000,然后想在 datasetprovider的beforupdaterecord中使用语句: try adocon ...