POJ-1932

#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");
    }
}

發佈了69 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章