#include <stdio.h>
#define MAX 110
#define QMAX 1000
int energys[MAX][MAX];
int cost[MAX][MAX];
int doors;
// 计算有向图的传递闭包
void allcosts(int n)
{
int i, j, k;
for (k = 1; k <= n; k++)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
if (cost[i][j] = cost[i][j] || cost[i][k] && cost[k][j])
;
}
// 使用SPFA算法计算带有负权值的图的最短路径
void spfa(int x)
{
int i, door;
int in_queue[MAX] = {0}, num[MAX] = {0};
int queue[QMAX] = {0}, front, rear;
int d[MAX];
d[x] = 100;
for (i = 2; i <= doors; i++) {
d[i] = -100000;
}
front = rear = 0;
rear = (rear+1)%QMAX;
queue[rear] = x;
in_queue[x] = 1;
num[x]++;
while (front != rear) {
front = (front+1)%QMAX;
door = queue[front];
in_queue[door] = 0;
// 当某个结点的入队次数大于N,则存在负环(SPFA算法的最多松弛次数为N-1)
if (num[door] <= doors)
for (i = 1; i <= doors; i++) {
if (energys[door][i] != -100000) {
// 判断“d[door]+energys[door][i] > 0“是为了确保去到每个结点的权值都是大于0(以防到达N结点的路径出现负权值)
if (d[i] < d[door]+energys[door][i] && d[door]+energys[door][i] > 0) {
d[i] = d[door]+energys[door][i];
if (!in_queue[i]) {
rear = (rear+1)%QMAX;
queue[rear] = i;
in_queue[i] = 1;
num[i]++;
}
}
}
}
else {
// 这个负环有没有存在一条路径通向N结点
if (cost[door][doors])
d[doors] = 1;
}
// 当已经找到一条路径从1结点到N结点的权值大于0(可能不是最大路径),就可以判断为”winnable“
if (d[doors] > 0) {
printf("winnable\n");
return;
}
}
printf("hopeless\n");
return;
}
int main()
{
int i, j;
int value, doorways;
while (scanf("%d", &doors) && doors != -1) {
for (i = 1; i <= doors; i++) {
scanf("%d%d", &value, &doorways);
// 初始化 energys数组
for (j = 1; j <= doors; j++) {
energys[i][j] = -100000;
cost[i][j] = 0;
}
energys[i][i] = 0;
while (doorways--) {
scanf("%d", &j);
energys[i][j] = value;
cost[i][j] = 1;
}
}
allcosts(doors);
// 如果结点1和结点N是连通的,使用SPFA算法
if (cost[1][doors])
spfa(1);
else
printf("hopeless\n");
}
}
POJ-1932
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.