1. 程式人生 > >UVa 1599 Ideal Path

UVa 1599 Ideal Path

給一個n個頂點m條邊 的無向圖。每條邊上都塗有一種顏色。求從結點1 到 結點n 的一條路徑, 使得經過的邊數儘量少,在此前提下, 經過的邊的顏色的序列的字典序最小。

一對節點間可能有多條邊,一條邊可能連線兩個相同結點。輸入保證結點1 可以到達結點n。

這裡用陣列模擬連結串列來儲存邊。我們首先一次逆向bfs()構造分層網路。然後正向bfs每一步沿著分層步數遞減的方向走,每次走的時候標記上在哪一層上走的哪一個顏色邊

。這裡絕對是個技巧。因為佇列中出來的元素必然是兄弟結點全部出來完之後, 才會彈出這些兄弟結點的第一個作為接下來子樹的根節點,所以用層數陣列可以記錄一層邊

的顏色最小值, 即使他有多個堂兄弟。這樣是完全可以理解的。

需要說明的一點是 構造分層網路時用到的vis陣列,必須初始化為-1,否則存在bug,比如這組:

3 2

1 3 2

2 3 3

答案是:

1

2

才對。

但是a掉之後 即使vis置為0,也過了。

還有就是在找每個兄弟結點和孩子連邊中的最小色彩值的時候。不知道為什麼我把tmp設為足夠大。然後每步更新tmp直至最小,這樣提交結果卻是wa。很是鬱悶。

/*=============================================================================   
#   
#      Author: liangshu - cbam    
#   
#      QQ : 756029571    
#   
#      School : 哈爾濱理工大學    
#   
#      Last modified: 2015-11-18 19:54  
#   
#     Filename: H.cpp   
#   
#     Description:    
#        The people who are crazy enough to think they can change the world, are the ones who do !    
=============================================================================*/   
  
#include<iostream>  
#include<sstream>  
#include<algorithm>  
#include<cstdio>  
#include<string.h>  
#include<cctype>  
#include<string>  
#include<cmath>  
#include<vector>  
#include<stack>  
#include<queue>  
#include<map>  
#include<set>  
using namespace std; 
const int INF=400004;
int inq[INF];
int cnt[INF];
int low[INF];
int head[INF];
int n,m,c;
struct Edge
{
    int next_edge,v,t,val;
} edge[INF];

void bfs1(int p){
    memset(low, -1, sizeof(low));
    low[p] = 0;
    queue<int>q;
    q.push(p);
    while(!q.empty()){
        int u = q.front();
        if(u == 1){
            return ;
        }
        q.pop();
        for(int e = head[u]; e != -1; e = edge[e].next_edge){
            if(low[edge[e].v] == -1 && edge[e].v != n){
                low[edge[e].v] = low[u] + 1;
                q.push(edge[e].v);

            }
        }
    }
}
struct Node
{
    int x;
    Node(int x):x(x){
    }
};
 int ans[INF];
 int vis[INF];
  void bfs(int p){
      memset(ans, 0, sizeof(ans));
      memset(vis, 0, sizeof(vis));
     queue<Node>q;
     q.push(Node(p));
     while(!q.empty()){
        int e = q.front().x;
        int tmp = -1;
        q.pop();
        for(int i = head[e]; i != -1; i = edge[i].next_edge){
            if(low[edge[i].v] == low[e] - 1){
                if(tmp == -1){
                    tmp = edge[i].val;
                }
                else{
                    tmp = min(edge[i].val, tmp);
                }
            }
        }
            int t = low[1] - low[e];
            if(ans[t] == 0){
                ans[t] = tmp;
            }
            else{
                ans[t] = min(tmp, ans[t]);
            }
            for(int i = head[e]; i != -1; i = edge[i].next_edge){
                if(!vis[edge[i].v] && edge[i].val == tmp  && low[edge[i].v] == low[e] - 1){
                    q.push(edge[i].v);
                    vis[edge[i].v] = 1;
                }
            }
       }
  }
int main()
{
    int x,y,z;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        memset(head,-1,sizeof(head));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d", &x, &y, &z);
            if(x == y){
                continue;
            }
            edge[i].next_edge=head[x];
            edge[i].v=y;
            edge[i].t=1;
            edge[i].val = z;
            head[x]=i;

            edge[i+m].next_edge=head[y];
            edge[i+m].v=x;
            edge[i+m].t=1;
            edge[i+ m].val = z;
            head[y]=i+m;
        }
        bfs1(n);
        bfs(1);
        printf("%d\n%d", low[1], ans[0]);
        for(int i = 1; i < low[1]; i++)
        printf(" %d", ans[i]);
        printf("\n");
    }
    return 0;
}
/*
4 5
1 2 3
2 3 345
3 4 2
4 2 2
1 3 1
*/