题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4076
题意:有n*m个点,每一点可以向四个方向走,有些点是墓地不能走,有些点是山洞,当你走到该点时会传送到另外一点,所花费的时间有可能是个正数也可能是个负数
也可能是0。起点是(0,0),目的地是(n-1,m-1),题目保证起点和终点不会是墓地也不会是山洞。如果有可能永远都到达不了终点也就是该图存在负权回路,输出Never;
否则输出需最少的花费时间或者Impossible;
思路:存在负权,显然要用spfa。当对某一个点的松弛次数超时该图的顶点数n*m时就表示存在负权回路。
但是有一点需要注意:判断负权回路的时候不能把终点算在内,因为当第一次走到终点的时候就走出去了,终点不会对他的后继点进行松弛。
code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # include<stdio.h>
2 # include<string.h>
3 # include<queue>
4 using namespace std;
5 # define N 35
6 # define INF 0xfffffff
7 int dir[4][2]={0,1,0,-1,1,0,-1,0};
8 struct node{
9 int x,y;
10 };
11 int map[N][N],visit[N][N];
12 int count1[N][N],mark[N][N];
13 int xx[N][N],yy[N][N],tt[N][N];
14 int n,m,flag;
15 void bfs()
16 {
17 int i,ans;
18 queue<node>q;
19 node cur,next;
20 cur.x=0;
21 cur.y=0;
22 q.push(cur);
23 visit[0][0]=0;
24 mark[0][0]=1;
25 count1[0][0]++;
26 while(!q.empty())
27 {
28 cur=q.front();
29 mark[cur.x][cur.y]=0;
30 q.pop();
31 if(count1[cur.x][cur.y]>n*m) {flag=1;return;}
32 if(cur.x==n-1 && cur.y==m-1) continue;
33 if(xx[cur.x][cur.y]!=-1)
34 {
35 next.x=xx[cur.x][cur.y];
36 next.y=yy[cur.x][cur.y];
37 ans=visit[cur.x][cur.y]+tt[cur.x][cur.y];
38 if(visit[next.x][next.y]>ans)
39 {
40 visit[next.x][next.y]=ans;
41 if(mark[next.x][next.y]==0)
42 {
43 mark[next.x][next.y]=1;
44 count1[next.x][next.y]++;
45 q.push(next);
46 }
47 }
48 continue;
49 }
50 for(i=0;i<4;i++)
51 {
52 next.x=cur.x+dir[i][0];
53 next.y=cur.y+dir[i][1];
54 ans=visit[cur.x][cur.y]+1;
55 if(next.x<0 || next.y<0 || next.x>=n || next.y>=m || map[next.x][next.y]==1) continue;
56 if(visit[next.x][next.y]>ans)
57 {
58 visit[next.x][next.y]=ans;
59 if(mark[next.x][next.y]==0)
60 {
61 mark[next.x][next.y]=1;
62 count1[next.x][next.y]++;
63 q.push(next);
64 }
65 }
66 }
67 }
68 }
69 int main()
70 {
71 int i,j,num,a,b;
72 while(scanf("%d%d",&n,&m)!=EOF)
73 {
74 if(n==0 && m==0) break;
75 scanf("%d",&num);
76 memset(map,0,sizeof(map));
77 while(num--)
78 {
79 scanf("%d%d",&a,&b);
80 map[a][b]=1;
81 }
82 scanf("%d",&num);
83 memset(xx,-1,sizeof(xx));
84 while(num--)
85 {
86 scanf("%d%d",&a,&b);
87 scanf("%d%d%d",&xx[a][b],&yy[a][b],&tt[a][b]);
88 }
89 memset(mark,0,sizeof(mark));
90 memset(count1,0,sizeof(count1));
91 for(i=0;i<=n;i++)
92 for(j=0;j<=m;j++)
93 visit[i][j]=INF;
94 flag=0;
95 bfs();
96 if(flag==1) {printf("Never\n");continue;}
97 if(visit[n-1][m-1]==INF) printf("Impossible\n");
98 else printf("%d\n",visit[n-1][m-1]);
99 }
100 return 0;
101 }