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. webbroswer 后台注入脚本 的方法

    HtmlElement script = webBrowser.Document.CreateElement("script"); script.SetAttribute(&quo ...

  2. JavaScript设计模式(一)

    使用JavaScript框架和库过程中, 我遇到过很多感觉上'奇形怪状'的代码. 大多数情况下, 按照惯例编写代码也能够写出很多出色的功能. 但是如果不从根本上理解它们实现的方法, 就没办法完全充分发 ...

  3. Error:(6, 0) No such property: outputDir for class: org.gradle.api.internal.project.DefaultProject_Decorated

    在学习greenDao过程中build.gradle文件中出现这个错误,找了半天不知道为什么.代码我是在git上下载的Demo,按理说应该是没问题的.到最后发现缺少了一个关键字Def // 这样有问题 ...

  4. EPP3怎么安装SVN(EclipsePHP Studio 3.0)

    如果你和我一样,喜欢用eclipse,你想用用他来开发PHP,那么EPP是一个不错的选择(个人觉得,中文版的有点不习惯) 我们一般都用svn来进行版本控制和代码共享,但是用epp3的时候会遇到这么一个 ...

  5. ERwin 连接 mysql

    1. install mysql connector; 2. run odbc connection management (c:\windows\syswow64\odbcad32.exe); 3. ...

  6. C#变量初始化问题:字段初始值无法引用非静态字段、方法或属性

    http://www.cnblogs.com/bluestorm/p/3432190.html 问题:字段初始值设定项无法引用非静态字段.方法或属性的问题 下面代码出错的原因,在类中定义的字段为什么不 ...

  7. 轮子来袭 vJine.Core Orm 之 02_代码生成

    1.下载并安装动软代码生成器: 2.下载vJine.Core.Orm模板: 3.解压模本文件并复制到如下的动软代码生成器模板目录: 4.打开动软代码生成器会看到模板已识别加载: 5.选择模板代码批量生 ...

  8. 【开发】Form Validate 表单验证 扩展应用

    目录: ★.文本输入框(easyui-textbox) ★.数字框(easyui-numberbox) ★.时间(easyui-datebox) ★.文本域(easyui-textbox easyui ...

  9. bzoj2287:[POJ Challenge]消失之物

    思路:首先先背包预处理出f[x]表示所有物品背出体积为x的方案数.然后统计答案,利用dp. C[i][j]表示不用物品i,组成体积j的方案数. 转移公式:C[i][j]=f[j]-C[i][j-w[i ...

  10. print neatly 整齐打印 算法导论

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098562.html 题目链接:print neatly 整齐打印 算法导论 考虑在一个打印 ...