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