您的位置:首页 > Web前端

poj3592--Instantaneous Transference(强连通缩点+spfa)

2015-05-16 17:13 204 查看
poj3592:题目链接

题目大意:给出n*m的矩阵,其中数字代表矿物的数量,#代表不可达,*代表传送门,传送到给定的位置。问最多可以收集多少矿物(每个矿物只能被收集一次,可以经过多次)

因为存在传送门,所以就会形成环,用强连通将形成环的缩成一个点,记录每个点代表的矿物数,最后用spfa找出最长路,也就是可以得到的最多的矿物数。(不会出现矩阵外的点)

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std ;
struct node
{
int u , v ;
int next ;
} edge[10000] , tree[10000] ;
char Map[50][50] ;
int head[2000] , h_tree[2000] , cnt ;
int low[2000] , dnf[2000] , time ;
int vis[2000] , belong[2000] , num ;
int sum[2000] , n , m , dis[2000];
stack <int> sta ;
queue <int> que ;
void init()
{
cnt = time = num = 0 ;
while( !sta.empty() ) sta.pop() ;
while( !que.empty() ) que.pop() ;
memset(head,-1,sizeof(head)) ;
memset(h_tree,-1,sizeof(head)) ;
memset(low,0,sizeof(low)) ;
memset(dnf,0,sizeof(dnf)) ;
memset(vis,0,sizeof(vis)) ;
memset(belong,0,sizeof(belong)) ;
memset(sum,0,sizeof(sum)) ;
memset(Map,0,sizeof(Map)) ;
}
void add(int u,int v)
{
edge[cnt].u = u ;
edge[cnt].v = v ;
edge[cnt].next = head[u] ;
head[u] = cnt++ ;
}
void add_tree(int u,int v)
{
tree[cnt].u = u ;
tree[cnt].v = v ;
tree[cnt].next = h_tree[u] ;
h_tree[u] = cnt++ ;
}
void tarjan(int u)
{
dnf[u] = low[u] = ++time ;
vis[u] = 1 ;
sta.push(u) ;
int i , v , j ;
for( i = head[u] ; i != -1 ; i = edge[i].next )
{
v = edge[i].v ;
if( !dnf[v] )
{
tarjan(v) ;
low[u] = min(low[u],low[v]) ;
}
else if( vis[v] )
{
low[u] = min(low[u],dnf[v]) ;
}
}
if( low[u] == dnf[u] )
{
++num ;
while( 1 )
{
j = sta.top() ;
sta.pop() ;
vis[j] = 0 ;
belong[j] = num ;
if( Map[j/m][j%m] != '*' )
sum[num] += Map[j/m][j%m] - '0' ;
if(j == u) break ;
}
}
}
int spfa(int u)
{
memset(vis,0,sizeof(vis)) ;
memset(dis,-1,sizeof(dis)) ;
dis[u] = sum[u] ;
vis[u] = 1 ;
que.push(u) ;
int i , v , max1 = sum[u] ;
while( !que.empty() )
{
u = que.front() ;
que.pop() ;
vis[u] = 0 ;
for(i = h_tree[u] ; i != -1 ; i = tree[i].next)
{
v = tree[i].v ;
if( dis[v] < dis[u] + sum[v] )
{
dis[v] = dis[u] + sum[v] ;
max1 = max(max1,dis[v]) ;
if( !vis[v] )
{
vis[v] = 1 ;
que.push(v) ;
}
}
}
}
return max1 ;
}
int main()
{
int t , i , j ;
int u , v , k ;
scanf("%d", &t) ;
while( t-- )
{
init() ;
scanf("%d %d", &n, &m) ;
for(i = 0 ; i < n ; i++)
scanf("%s", Map[i]) ;
for(i = 0 ; i < n ; i++)
{
for(j = 0 ; j < m ; j++)
{
if( Map[i][j] == '#' ) continue ;
if( Map[i][j] == '*' )
{
scanf("%d %d", &u, &v) ;
if(u < n && v < m && Map[u][v] != '#' )
add(i*m+j,u*m+v) ;
}
if( i < n-1 && Map[i+1][j] != '#' )
add(i*m+j,(i+1)*m+j) ;
if( j < m-1 && Map[i][j+1] != '#' )
add(i*m+j,i*m+j+1) ;
}
}
for(i = 0 ; i < n*m ; i++)
if( !dnf[i] && head[i] != -1 ) tarjan(i) ;
for(i = 0 , cnt = 0 ; i < n*m ; i++)
for(j = head[i] ; j != -1 ; j = edge[j].next)
{
u = belong[ edge[j].u ] ;
v = belong[ edge[j].v ] ;
if( u != v )
add_tree(u,v) ;
}
printf("%d\n", spfa( belong[0] ) ) ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: