poj 3592 缩点+SPFA
题意:给出一个矩阵,其中#代表墙,不可走,0-9代表权值,*代表可以选择传送。求从0,0点开始出发能获得最大权值。
思路:因为*的出现会有环的情况,先建图连边,将环进行Tarjan缩点,之后再从0,0用SPFA找最长路就行了。
麻烦的地方在于建图,还有各种错
代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 1605 #define MAXM 1605*1605 #define inf 10000000 int map[MAXN][MAXN],DFN[MAXN],Low[MAXN],vis[MAXN]; int stack[MAXM],instack[MAXN],Belong[MAXN],a[MAXN],b[MAXN]; int que[1605*MAXN],sign[1605*MAXN],dis[1605*MAXN],head[1605*MAXN],val[1605*MAXN]; int G[MAXN][MAXN]; char g[50][50]; int kt,n,m,count1,scnt,top,tot; struct Edge { int to,next; }edge[MAXM]; void addedge(int v,int w) { edge[tot].to=w; edge[tot].next=head[v]; head[v]=tot++; } void SPFA(int s) { memset(sign,false,sizeof(sign)); for(int i=1;i<=scnt;i++) { dis[i]=0; } int l,r; l=r=0; que[r++]=s; sign[s]=true; dis[s]=val[s]; while(l!=r) { int v=que[l++]; sign[v]=true; for(int i=head[v];i!=-1;i=edge[i].next) { int j=edge[i].to; if(dis[j]<=dis[v]+val[j]) { dis[j]=dis[v]+val[j]; if(!sign[j]) { sign[j]=true; que[r++]=j; } } } sign[v]=false; } } void Tarjan(int v) { instack[v]=1; stack[top++]=v; DFN[v]=Low[v]=++count1; for(int i=0;i<n*m;i++) { if(map[v][i]==1) { if(!DFN[i]) { Tarjan(i); Low[v]=min(Low[v],Low[i]); } else if(instack[i]==1) { Low[v]=min(Low[v],DFN[i]); } } } int t; if(DFN[v]==Low[v]) { scnt++; do { t=stack[--top]; instack[t]=0; Belong[t]=scnt; }while(t!=v); } } void dfs(int x,int y) { vis[x*m+y]=1; if(g[x][y]=='#') return ; if(g[x][y]>='a'&&g[x][y]<='a'+kt) { int t=g[x][y]-'a'; if(!map[x*m+y][a[t]*m+b[t]]&&x*m+y!=a[t]*m+b[t]) { map[x*m+y][a[t]*m+b[t]]=1; if(!vis[a[t]*m+b[t]]) dfs(a[t],b[t]); } } if(x+1<n&&g[x+1][y]!='#') { if(!map[x*m+y][(x+1)*m+y]) { map[x*m+y][(x+1)*m+y]=1; if(!vis[(x+1)*m+y])dfs(x+1,y); } } if(y+1<m&&g[x][y+1]!='#') { if(!map[x*m+y][x*m+y+1]) { map[x*m+y][x*m+y+1]=1; if(!vis[x*m+y+1])dfs(x,y+1); } } } int main() { int T; scanf("%d",&T); while(T--) { memset(g,'\0',sizeof(g)); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%s",g[i]); } kt=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(g[i][j]=='*') { kt++; g[i][j]='a'+kt; } } } for(int i=1;i<=kt;i++) { scanf("%d%d",&a[i],&b[i]); } memset(map,0,sizeof(map)); memset(vis,0,sizeof(vis)); dfs(0,0); memset(DFN,0,sizeof(DFN)); memset(instack,0,sizeof(instack)); memset(stack,0,sizeof(stack)); memset(Low,0,sizeof(Low)); memset(Belong,0,sizeof(Belong)); count1=scnt=top=0; Tarjan(0); memset(val,0,sizeof(val)); for(int i=0;i<n*m;i++) { if(g[i/m][i%m]<='9'&&g[i/m][i%m]>='0') { val[Belong[i]]+=g[i/m][i%m]-'0'; } } tot=0; memset(head,-1,sizeof(head)); memset(G,0,sizeof(G)); for(int i=0;i<n*m;i++) { for(int j=0;j<n*m;j++) { if(map[i][j]&&Belong[i]!=Belong[j]) { if(!G[Belong[i]][Belong[j]]) { addedge(Belong[i],Belong[j]); G[Belong[i]][Belong[j]]=1; //cout<<Belong[i]<<','<<Belong[j]<<endl; } } } //cout<<Belong[i]<<' '; } SPFA(Belong[0]); int ans=0; for(int i=1;i<=scnt;i++) { if(dis[i]>ans) ans=dis[i]; } printf("%d\n",ans); } return 0; } /* 100 2 2 ** *9 0 1 0 1 0 0 */