#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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.