白书数据结构一章中最后一根刺拔掉了! 这题网上大部分都说都是SPFA ,,但是卡了我一个星期dfs 终于给我过掉了
题意:一个有向图,每个节点都有一个值(可能小于0),给定你起始点和初始能量和终点,问你最终在 能量值大于0的情况下能否到达终点
解题思路:dfs,bfs都试过了,最终还是用两个dfs过了,第一个dfs是判断下一个节点是否能走(依赖于第二个dfs)如果能走,如果这个节点在这条路径中走过,如果走过那么判断环的正负,如果是负环就进行第二个dfs判断能否到终点(在途中标记所有的点,如果能走到 则答案为win 如果不能,途中所有的点都不能了)!!
如果这个节点没有走过,那么看到这个节点的之是否大于其他路径到这个节点的值(初始值 = 0 所以不用判断 是否 > 0 的情况) ,如果大于,则继续走下去!
解题代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> int map[105][105]; int limits[105]; int value[105]; int visit[105]; int valuevisit[105]; int vvisit[105]; int canvisit[105]; int n,ok; void ddfs(int k) { if(ok) return; if(k == n) { ok = 1; return; } for(int i = 1;i <= limits[k]; i++ ) { if(!canvisit[map[k][i]]) { canvisit[map[k][i]] = 1; ddfs(map[k][i]); } } } void dfs(int k, int sum) { if(k == n && sum >0 ) { ok = 1; return; } if(ok) return; for(int i = 1; i <= limits[k]; i ++) { if(!canvisit[map[k][i]]) { if(visit[map[k][i]]) { if(sum + value[map[k][i]] > valuevisit[map[k][i]]) { canvisit[map[k][i]] = 1; ddfs(map[k][i]); } } else if(sum + value[map[k][i]] > vvisit[map[k][i]]) { visit[map[k][i]] = 1; valuevisit[map[k][i]] = sum + value[map[k][i]]; vvisit[map[k][i]] = sum + value[map[k][i]]; dfs(map[k][i],valuevisit[map[k][i]]); valuevisit[map[k][i]] = 0; visit[map[k][i]] = 0; } } } } int main() { while(scanf("%d",&n) != EOF) { if(n == -1) break; ok = 0; memset(map,0,sizeof(map)); memset(visit,0,sizeof(visit)); memset(vvisit,0,sizeof(vvisit)); memset(canvisit,0,sizeof(canvisit)); memset(value,0,sizeof(value)); for(int i =1;i <= n;i ++) { scanf("%d %d",&value[i],&limits[i]); for(int j = 1;j <= limits[i]; j++) scanf("%d",&map[i][j]); } visit[1] = 1; valuevisit[1] = 100; dfs(1,100); if(ok) printf("winnable "); else printf("hopeless "); } return 0; }
在解题过程中,发现下面的有明显缺陷(在dfs后没有标记掉,判断的环不一定是一个有向环,而且也不是同一路径的环)的代码也能AC, uva的数据还是有点弱啊
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include<math.h> #include<limits.h> struct point { int value; int k; int a[103]; }points[105]; int begin,end,ok ,n; int visit[105]; int vvisit[105]; int isvisit[105]; void dfs1(int p) { //printf("%d ",p); if(p == n) { ok = 1; return; } if(ok) return ; for(int i = 1;i <= points[p].k;i ++) { if(!isvisit[points[p].a[i]]) { isvisit[points[p].a[i]] = 1; dfs1(points[p].a[i]); } } return ; } void dfs(int p ,int v) { //printf("%d ",p); if(v <= 0 ) return; if(p == n) { ok = 1; return; } if(ok) return ; for(int i = 1;i <= points[p].k;i ++) { if(!visit[points[p].a[i]]) { visit[points[p].a[i]] = v + points[points[p].a[i]].value; dfs(points[p].a[i],v+points[points[p].a[i]].value); } else { if(v + points[points[p].a[i]].value > visit[points[p].a[i]] ) { isvisit[points[p].a[i]] = 1; dfs1(points[p].a[i]); return; } } } return ; } int main(){ //freopen("/home/plac/problem/input.txt","r",stdin); //freopen("/home/plac/problem/output.txt","w",stdout); while(scanf("%d",&n) != EOF) { if(n == -1) break; begin = 0 ; end = 0 ; ok = 0 ; memset(points,0,sizeof(points)); memset(visit,0,sizeof(visit)); memset(vvisit,0,sizeof(vvisit)); memset(isvisit,0,sizeof(isvisit)); for(int i = 1; i <= n;i ++) { scanf("%d %d",&points[i].value,&points[i].k); for(int j =1 ;j <= points[i].k;j ++) { scanf("%d",&points[i].a[j]); } } visit[1] = 100 ; dfs(1,100); if(!ok) printf("hopeless "); else printf("winnable "); } return 0 ; }