UVA-10557
题意:初始有100点能量,每经过一个房间会加上那个房间的能量,能量小于0就不能动了,给出每个房间的能量和它能到的若干个房间的房间号,求最后能不能到达第n个房间。
解题思路1:
看题解看到的,用DFS+BFS来做。
我们可以发现,如果存在一个正权环(一圈走下来值会增加),那么就可以在这里刷到足够多的能量再往终点走,所以发现一个正权环(DFS),我们只要判断环上的点有没有到n的路径(BFS)。用DFS跑,如果一个点已经被走过,而且还存在一条路径到它且能量值比之前还多,我们就能当他存在一个正权环。(2333333。然而这条件太弱,UVA数据也是萌萌的,居然能过。)然后用这个点去BFS判断能不能到终点。这只能说是玄学。
DFS+BFS代码:
/*************************************************************************
> File Name: UVA-10557.cpp
> Author: Narsh
>
> Created Time: 2016?07?21? ??? 09?09?20?
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
struct node{
int val,l;
int w[110];
} room[110];
int energy[110],n,q[110000];
bool pd[110],flag;
void bfs(int x) {
memset(pd,true,sizeof(pd));
int h=0,t=1;
q[t]=x;
pd[x]=false;
while (h < t) {
int now = q[++h];
for (int i = 1; i <= room[now].l; i++) {
int m = room[now].w[i];
if (pd[m]){
pd[m]=false;
q[++t] = m;
if(q[t] == n) {
flag =true;
return ;
}
}
}
}
}
void dfs(int x, int val) {
if (flag) return ;
if (x == n) {
flag= true;
return ;
}
energy[x] = val +room[x].val;
for (int i = 1; i <= room[x].l; i++) {
int m = room[x].w[i];
if (energy[x] + room[m].val > 0) {
if (!energy[m]) {
dfs(m, energy[x]);
if (flag) return ;
} else
if (energy[x] + room[m].val > energy[m]) {
bfs(m);
if (flag) return ;
}
}
}
}
int main() {
while (scanf("%d",&n) && n != -1) {
for (int i = 1; i <= n; i++) {
scanf("%d%d",&room[i].val,&room[i].l);
for (int j = 1; j <= room[i].l; j++)
scanf("%d",&room[i].w[j]);
}
memset(energy,0,sizeof(energy));
flag=false;
dfs(1,100);
if (flag) printf("winnable\n");
else printf("hopeless\n");
}
}
0 2 2 3
-90 1 4
40 1 2
-60 1 5
0 0
这个数据应该是到不了的,DFS+BFS显示是可以的。
UVA-10557 正解:SPFA求最大路径。
解题思路:SPFA可以用来求最短路径,同样的我们把条件改下就可以用它来求最大路径。和求最短路径不能处理负权环一样,改求最大路径之后,正权环也是要通过控制次数来避免死循环,每次正权环假设只增加1,环有100个,路径最大负值约100*100,进入100^3次就是极限了。然后我们只要判断dis[n]>0,成立就是有结果了。
SPFA代码
/*************************************************************************
> File Name: UVA-10557.cpp
> Author: Narsh
>
> Created Time: 2016?07?21? ??? 09?09?20?
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
struct node{
int val,l;
int w[110];
} room[110];
int dis[110],n,q[110000];
bool pd[110],flag,vis[110];
int main() {
while (scanf("%d",&n) && n != -1) {
for (int i = 1; i <= n; i++) {
scanf("%d%d",&room[i].val,&room[i].l);
for (int j = 1; j <= room[i].l; j++)
scanf("%d",&room[i].w[j]);
}
flag=false;
for (int i = 1; i <= n; i++) {
vis[i]=true;
dis[i]=0;
}
dis[1]=100;
vis[1]=false;
q[0]=1;
int h=0,t=1,m=0;
while(h != t) {
if (m > 10000000) break;
int now = q[h];
for (int i = 1 ;i <= room[now].l; i++) {
int x = room[now].w[i];
if (dis[now] + room[x].val > dis[x]) {
dis[x]=dis[now] +room[x].val;
if (vis[x]) {
q[t]=x;
t=(t+1)%100;
vis[x]=false;
++m;
}
}
}
vis[now]=true;
h=(h+1)%100;
if (dis[n] > 0) {
flag=true;
break;
}
}
if (flag) printf("winnable\n");
else printf("hopeless\n");
}
}