poj_1923_XYZZY

来源:互联网 发布:防身折叠式铁扇子淘宝 编辑:程序博客网 时间:2024/06/06 09:41

一道最短路径的入门好题,判环+传递闭包+spfa

题目大意:

输入第一行表示有n个点,接下来n行,第一个值为这个点的权值,第二个值k为它与k个点相连,接下来k个值为与它相连的k个点.

你的初始值生命值为100,问能否从1点到n点.1到n点保证可达

解题思路:

这个图的模型比较好建立,首先判定图中是否有正环以及,由于n较小(100)可以用弗洛伊德算法传递闭包,确定每个点到n点是否可达. 然后用spfa求最长路径,并判断正环,若有正环那一定能出去.


源代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <queue>using namespace std;const int N=110;bool Hash[N],rec[N];bool map[N][N],graph[N][N];int n;int cnt[N],dis[N],node[N];void init(){memset(Hash,false,sizeof(Hash));memset(rec,false,sizeof(rec));memset(map,false,sizeof(map));memset(graph,false,sizeof(graph));memset(cnt,0,sizeof(cnt));memset(dis,0,sizeof(dis));int x,y,k;for(k=1;k<=n;k++){scanf("%d",&node[k]);scanf("%d",&y);for(x=0;x<y;x++){int a;scanf("%d",&a);map[k][a]=graph[k][a]=true;}}/*while(scanf("%d%d",&x,&y),x!=0||y!=0){node[k]=x;int i;for(i=0;i<y;i++){scanf("%d",&x);map[k][x]=graph[k][x]=true;}k++;}*/}void floyd(){int k,i,j;for(k=1;k<=n;k++)for(i=0;i<=n;i++)for(j=0;j<=n;j++)map[i][j]=map[i][j]||(map[i][k]&&map[k][j]);for(i=1;i<=n;i++)if(map[i][n])rec[i]=true;rec[n]=true;}void spfa(){if(!rec[1]){puts("hopeless");return ;}queue<int> q;q.push(1);Hash[1]=true;dis[1]=100;while(!q.empty()){int x=q.front();q.pop();Hash[x]=false;if(++cnt[x]>n||x==n){puts("winnable");return ;}for(int i=1;i<=n;i++){if(rec[i]&&graph[x][i]&&dis[i]<dis[x]+node[i]){dis[i]=dis[x]+node[i];if(!Hash[i]){Hash[i]=false;q.push(i);}}}}puts("hopeless");}int main(){while(scanf("%d",&n),n>=0){init();floyd();spfa();}return 0;}


原创粉丝点击