您的位置:首页 > Web前端

poj 3592 Instantaneous Transference tarjan缩点 最长路 ++tarjan模版 && spfa最长路模版

2011-09-06 00:50 513 查看
/*
题意:给定一个矩阵,西南角为起点,每个单元都有一定价值的金矿(#表示岩石,不可达,*表示时空门,可以到达指定单元)
现在要求得最多可以获得多大利益
题解:强联通分量,最长路;如果没有时空门,就是纯粹的有向无环图的最长路了,现在出现时空门了,只要求强联通分量进行       缩点,对缩点后的图建立有向无环图,然后求最长路就ok了
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
using namespace std;
const int MAXV=49*49;
int n,m;

int value[MAXV];
char graph[41][41];

struct spfa//  spfa求最长路
{
static const int INF =-(1<<30);
struct Edge {
int v,next;
int w;
} ep[MAXV*MAXV];
int first[MAXV];
int d[MAXV];
int e;
int V;
inline void init(int n)
{
memset(first,-1,sizeof(first));
e=0;
V=n;
}
void addEdge(int u, int v, int dd) {
ep[e].v=v;
ep[e].w=dd;
ep[e].next=first[u];
first[u]=e++;
}
void solve(int source) {
static bool ok[MAXV];
memset(ok,false,sizeof(ok));
queue<int> q;
q.push(source);
for (int i = 0; i < V; i++) d[i] = INF;
d[source] = 0;
while(!q.empty())
{
int x=q.front();q.pop();
ok[x]=false;
for(int k=first[x];k!=-1;k=ep[k].next)
{
int v=ep[k].v;
if(d[v]<d[x]+ep[k].w)
{
d[v]=d[x]+ep[k].w;
if(ok[v]==false)
{
ok[v]=true;
q.push(v);
}
}
}
}
}
} g;
struct TarJan
{
struct Edge
{
int v,next;
}edge[4*MAXV];
int first[MAXV],ins[MAXV],dfn[MAXV],low[MAXV],Stack[MAXV],scc[MAXV];
int top,index,sccnum,e,V;
void init (int n)
{
e=0;V=n;
memset(first,-1,sizeof(first[0])*n);memset(ins,0,sizeof(ins[0])*n);
memset(dfn,0,sizeof(dfn[0])*n);  memset(low,0,sizeof(dfn[0])*n);
}
void addEdge(int u,int v)
{ edge[e].v=v;edge[e].next=first[u];first[u]=e++;}
void solve()
{
index=1;top=-1;sccnum=-1;
for(int i=0;i<V;i++)if(dfn[i]==0) tarjan(i);
}
void tarjan(int u)
{
int v;   low[u] = dfn[u] = index++;   Stack[++top]=u; ins[u] = true;
for (int k=first[u]; k!=-1; k=edge[k].next)
{
v = edge[k].v;
if (dfn[v] == 0) {  tarjan(v);  low[u]=min(low[u],low[v]); }
else if (ins[v]) {  low[u]=min(low[u],dfn[v]);  }
}
if (dfn[u] == low[u])  {  sccnum++;
do{v = Stack[top--];ins[v] = false; scc[v] = sccnum;}while(u != v); }
}
}my;
void init()
{
int x,y;
memset(value,0,sizeof(value));
my.init(n*m);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(graph[i][j]!='#')
{
if(i!=0)
my.addEdge((i-1)*m+j,i*m+j);
if(j!=0)
my.addEdge(i*m+j-1,i*m+j);
if(graph[i][j]=='*')
{
scanf("%d%d",&x,&y);
if(graph[x][y]!='#')
my.addEdge(i*m+j,x*m+y);
}
}
}
my.solve();
}
void solve()
{
g.init(my.sccnum+2);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(graph[i][j]!='*'&&graph[i][j]!='#')
{
value[my.scc[i*m+j]]+=graph[i][j]-'0';
}
}

for(int i=0;i<n*m;i++)
{
for(int k=my.first[i];k!=-1;k=my.edge[k].next)
{
int v=my.edge[k].v;
if(my.scc[i]!=my.scc[v])
{
g.addEdge(my.scc[i],my.scc[v],value[my.scc[v]]);
}
}
}
int ans=0;
g.solve(my.scc[0]);
for(int i=0;i<=my.sccnum;i++)
{
if(g.d[i]>ans)
ans=g.d[i];
}
printf("%d\n",ans+value[my.scc[0]]);
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",graph[i]);
}
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: