poj 1932 XYZZY

/* Name:poj 1932 XYZZY Author:Unimen Date: 21/04/11 16:51 Description:Floyd, SPFA变形应用 */ /* 解题报告: 先Floyd,求出在不考虑能量值的情况下是否能到达终点n 然后spfa, 如果终点进队列或者出现正环则一定能到达终点 注意: 1、这里没有用SPFA求最短路径,而是求了最长路径,不一定是最长路径是大于0的路径,根据SPFA算法 只要终点n入队,即可知道可到达终点 2、存在正环也一定可以走到最终的终点n 3、SPFA判断正环的方法:某个点入队的次数>n(n为图中的结点数) */ #include <iostream> #include <cstring> #include <queue> using namespace std; const int MAXN = 110; int g[MAXN][MAXN], mat[MAXN][MAXN], weight[MAXN], nolinkable[MAXN]; int n; int dis[MAXN], visited[MAXN], ct[MAXN]; int SPFA() { queue<int> que; dis[1] = 100; que.push(1); while(que.empty() == false) { int x; x = que.front(); que.pop(); visited[x] = 0; if(++ct[x]>n || x==n) return 1; for(int i=1; i<=n; i++) { if(g[x][i] && !nolinkable[i] && dis[i] < dis[x] + weight[i]) { dis[i] = dis[x] + weight[i]; if(!visited[i]) { que.push(i); visited[i] = 1; } } } } return false; } int main() { int i, j, k; int doorways, a; while(cin>>n && -1!=n) { memset(g, 0, sizeof(g)); memset(mat, 0, sizeof(mat)); //建图 for(i=1; i<=n; i++) { cin>>weight[i]; cin>>doorways; for(j=0; j<doorways; j++) { cin>>a; g[i][a] = 1; mat[i][a] = 1; } } //传闭包验证两点间的连通性 for(k=1; k<=n; k++) for(i=1; i<=n; i++) for(j=1; j<=n; j++) mat[i][j] = mat[i][j] || (mat[i][k] && mat[k][j]); if(!mat[1][n]) { cout<<"hopeless"<<endl; continue; } //看每一点到n是否能连通 memset(nolinkable, 0, sizeof(nolinkable)); for(i=2; i<n; i++) { if(!mat[i][n]) nolinkable[i] = 1; } memset(dis, 0, sizeof(dis)); memset(visited, 0, sizeof(visited)); memset(ct, 0, sizeof(ct)); cout<<(SPFA() ? "winnable" : "hopeless")<<endl; } return 0; }

你可能感兴趣的:(Date,算法)