POJ1874 Tram

 水题怡情。。。题目大意给你n个点,每个节点有k条出边和一个转换器,要到达节点需要启动转换器才能走到其他的相邻点上,转换器指的方向初始在当前点所指的第一个点。求从起点到终点所需要的最少启动转换器的次数。

之前觉得宽搜一遍应该就可以了,后来仔细想了下,发现只需要把每个点对应转换器的方向那条边赋权值为0,其他的赋权为1然后求一次单源最短路径就可以了,

因为没考虑-1的情况贡献一次WA。。。唉。。。

 

#include <iostream>
using namespace std;
const int MAXN = 200;
const int MAXM = MAXN*MAXN;
struct node
{
       int v, w, next;       
}mapp[MAXM];
int id;
int head[MAXN];
void init()
{
     id = 0;
     memset(head, -1, sizeof(head));     
}

void addedge(int u, int v, int w)
{
     mapp[id].v = v, mapp[id].w = w, mapp[id].next = head[u], head[u] = id ++;     
}
bool inque[MAXN];
int dist[MAXN];
int Que[10*MAXM];
const int inf = 1 << 30;
void SPFA(int s,int n)
{
     for (int i = 1; i <= n; i ++){
         inque[i] = false;
         dist[i] = inf;    
     }
     dist[s] = 0;
     inque[s] = true;
     int rear, front;
     rear = front = 0;
     Que[rear ++] = s;
     while (front < rear){
           int pre = Que[front ++];
           inque[pre] = false;
           for (int i = head[pre]; i != -1; i = mapp[i].next){
               int v = mapp[i].v;
               if (dist[v] > dist[pre] + mapp[i].w){
                   dist[v] = dist[pre] + mapp[i].w;
                   if (!inque[v]){
                      inque[v] = true;
                      Que[rear ++] = v;               
                   }
               }    
           }
     }
}
int main()
{
    int n, s, t;
    while (scanf("%d%d%d", &n, &s, &t) != EOF){
          init();
          for (int i = 1; i <= n; i ++){
              int a, b, c;
              scanf("%d", &a);
              int nc = 0;
              while (a --){
                    scanf("%d", &b);
                    if (!nc)addedge(i, b, 0);
                    else addedge(i, b, 1);
                    nc ++;
              }      
          }     
          SPFA(s, n);
          if (dist[t] == inf){
             printf("-1\n");            
          }
          else
          printf("%d\n", dist[t]);
    }
    return 0;    
}

你可能感兴趣的:(c)