XYZZY HDU1317

来源:互联网 发布:it 产业链 编辑:程序博客网 时间:2024/06/17 09:36

题意:一个游戏,从1号房间走到N号房间,每个房间都会有个能量值(可能为正,可能为负),每进入一个房间,房间的能量值就会加到玩家身上。

思路:求这个图的最长路,如果存在正环且正环能够到达终点则赢,或者到达终点时能量值大于0且整个过程中能量值大于0则赢。判断能不能到达用 Floyd 算法,求最长路用 BellmanFord 算法或 SPFA 算法。

下面是用 BellmanFord 和 Floyd 算法实现的。
自己实现过程中遇到的问题有:忘了每次初始化 G 数组为 0 。。。还有就是BellmanFord 用的不熟,,细节地方出了差错。
代码:

#include<cstdio>#include<cstring>#include<cstdlib>#include<stack>#include<queue>#include<utility>#include<vector>#include<cmath>#include<set>#include<map>#include<iostream>#include<algorithm>using namespace std;const int INF = 1000000;const int MAXN = 110;struct Edge{    int from, to;    Edge(){}    Edge(int a, int b):from(a),to(b){}};int n;int G[MAXN][MAXN];int value[MAXN];int d[MAXN];vector<Edge> edges;void Floyd(){    for(int k=1; k<=n; k++){        for(int i=1; i<=n; i++){            for(int j=1; j<=n; j++){                G[i][j] |= G[i][k]&G[k][j];  //Floyd算法判断能否到达            }        }    }}bool BellmanFord(int s){    for(int i=1; i<=n; i++) d[i] = -INF;    d[1] = 100;    for(int i=1; i<n; i++){        for(int j=0; j<edges.size(); j++){            int from = edges[j].from;            int to = edges[j].to;            if(d[to] < d[from]+value[to] && d[from]+value[to]>0){   //只有新的值大于 0 才能松弛                d[to] = d[from]+value[to];            }        }    }    for(int i=0; i<edges.size(); i++){        int from = edges[i].from;        int to = edges[i].to;        if(d[to] < d[from]+value[to] && d[from]+value[to]>0 && G[to][n]){   //如果存在环,且这个环能够到达终点那么 winnable            return true;        }    }    return d[n] > 0;}void Init(){    memset(G, 0, sizeof(G));    edges.clear();}int main(){    //freopen("in.txt", "r", stdin);    while(scanf("%d", &n) == 1 && n!=-1){        Init();        for(int i=1; i<=n; i++){            scanf("%d", &value[i]);            int m;            scanf("%d", &m);            while(m--){                int x;                scanf("%d", &x);                G[i][x] = 1;                edges.push_back(Edge(i, x));            }        }        Floyd();        if(G[1][n]){            if(BellmanFord(1)){                printf("winnable\n");            }            else{                printf("hopeless\n");            }        }        else{            printf("hopeless\n");        }    }    return 0;}

下面是用 Flyod 和 SPFA 算法写的

#include<cstdio>#include<cstring>#include<cstdlib>#include<stack>#include<queue>#include<utility>#include<vector>#include<cmath>#include<set>#include<map>#include<iostream>#include<algorithm>using namespace std;const int INF = 1000000;const int MAXN = 110;struct Edge{    int from, to;    Edge(){}    Edge(int a, int b):from(a),to(b){}};int n;int G[MAXN][MAXN];int value[MAXN];int d[MAXN];int time[MAXN];bool inq[MAXN];vector<Edge> edges;vector<int> M[MAXN];void Floyd(){    for(int k=1; k<=n; k++){        for(int i=1; i<=n; i++){            for(int j=1; j<=n; j++){                G[i][j] |= G[i][k]&G[k][j];  //Floyd算法判断连通性            }        }    }}bool SPFA(int s){    for(int i=1; i<=n; i++) d[i] = -INF;    d[s] = 100;    memset(inq, false, sizeof(inq));    memset(time, 0, sizeof(time));    queue<int> que;    que.push(s);    inq[s] = true;    while(!que.empty()){        int tmp = que.front();  que.pop();        inq[tmp] = false;        for(int i=0; i<M[tmp].size(); i++){            Edge &e = edges[M[tmp][i]];            if(d[e.to] < d[e.from]+value[e.to] && d[e.from]+value[e.to]>0 ){                d[e.to] = d[e.from]+value[e.to];                if(!inq[e.to]){                    inq[e.to] = true;                    if(++time[e.to] > n+1) {return G[e.to][n];}                    que.push(e.to);                }            }        }    }    return d[n] > 0;}void Init(){    memset(G, 0, sizeof(G));    for(int i=0; i<MAXN; i++){        M[i].clear();    }    edges.clear();}int main(){    //freopen("in.txt", "r", stdin);    while(scanf("%d", &n) == 1 && n!=-1){        Init();        for(int i=1; i<=n; i++){            scanf("%d", &value[i]);            int m;            scanf("%d", &m);            while(m--){                int x;                scanf("%d", &x);                G[i][x] = 1;                edges.push_back(Edge(i, x));                M[i].push_back(edges.size()-1);            }        }        Floyd();        if(G[1][n]){            if(SPFA(1)){                printf("winnable\n");            }            else{                printf("hopeless\n");            }        }        else{            printf("hopeless\n");        }    }    return 0;}
原创粉丝点击