UVa 1599 Ideal Path
阿新 • • 發佈:2019-02-10
給一個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 */