AtCoder arc061C Snuke's Subway Trip
大意:
给你一张无向图,边有种类。
当你第一次/重新进入某种边时费用 + 1
在同一种边之间行走无费用。
求 1 到 n 的最小费用。
嗯...乍一看有一个很直观的想法:记录每个点的最短路的上一条边的种类。
但是这个算法是个错的......有些数据能够hack掉。
由于边权只有0 & 1,考虑01BFS。
事实上我们还要记录每个点来之前的边,然后就要写结构体/pair
然后还要判重...
正解:考虑按照每个点的边的type拆点。
在不同点的同一type分点之间边权为0
原点与拆出来的点之间边权为1
然后跑01BFS即可。
开n个map来存点的分点编号。
map 的 count 用法(虽然没啥卵用)
我照着正解写了个过了,然后写了自己的想法就WA.....
不知道为什么。对拍可能生成的数据太弱了,全是符合的。
1 #include <cstdio> 2 #include <map> 3 #include <deque> 4 5 const int N = 1000010; 6 7 int cnt; 8 9 std::map<int, int> mp[N]; 10 11 struct Edge { 12 int v, nex, len; 13 }edge[N << 2]; int top; 14 15 int e[N], dis[N], vis[N]; 16 17 inline int get(int x, int type, int &f) { 18 if(mp[x][type]) { 19 f = 0; 20 return mp[x][type]; 21 } 22 f = 1; 23 return mp[x][type] = ++cnt; 24 } 25 26 inline void add(int x, int y, int z) { 27 ++top; 28 edge[top].v = y; 29 edge[top].len = z; 30 edge[top].nex = e[x]; 31 e[x] = top++; 32 edge[top].v = x; 33 edge[top].len = z; 34 edge[top].nex = e[y]; 35 e[y] = top; 36 return; 37 } 38 39 inline int BFS(int s, int t) { 40 vis[s] = 1; 41 dis[s] = 0; 42 std::deque<int> Q; 43 Q.push_back(s); 44 while(!Q.empty()) { 45 int x = Q.front(); 46 Q.pop_front(); 47 for(int i = e[x]; i; i = edge[i].nex) { 48 int y = edge[i].v; 49 if(vis[y]) { 50 continue; 51 } 52 dis[y] = dis[x] + edge[i].len; 53 if(y == t) { /// error : y == s 54 return dis[y]; 55 } 56 vis[y] = 1; 57 if(edge[i].len) { 58 Q.push_back(y); 59 } 60 else { 61 Q.push_front(y); 62 } 63 } 64 } 65 return -1; 66 } 67 68 int main() { 69 freopen("in.in", "r", stdin); 70 freopen("my.out", "w", stdout); 71 int n, m; 72 scanf("%d%d", &n, &m); 73 cnt = n; 74 for(int i = 1, x, y, z, f; i <= m; i++) { 75 scanf("%d%d%d", &x, &y, &z); 76 int x_type = get(x, z, f); 77 if(f) { 78 add(x, x_type, 1); 79 } 80 int y_type = get(y, z, f); 81 if(f) { 82 add(y, y_type, 1); 83 } 84 add(x_type, y_type, 0); 85 } 86 87 int ans = BFS(1, n); 88 printf("%d", ans >> 1); 89 90 return 0; 91 }
1 #include <cstdio> 2 #include <map> 3 #include <deque> 4 5 const int N = 100010; 6 7 std::map<int, int> mp[N]; 8 9 struct Edge { 10 int v, nex, type; 11 }edge[N << 4]; int top; 12 13 int e[N]; 14 15 inline void add(int x, int y, int z) { 16 top++; 17 edge[top].v = y; 18 edge[top].type = z; 19 edge[top].nex = e[x]; 20 e[x] = top; 21 return; 22 } 23 24 struct Poi { 25 int id, dis, pre; 26 Poi(int id, int dis, int pre) { 27 this->id = id; 28 this->dis = dis; 29 this->pre = pre; 30 } 31 }; 32 33 inline int BFS(int s, int t) { 34 std::deque<Poi> Q; 35 Q.push_back(Poi(s, 0, 0)); 36 while(!Q.empty()) { 37 Poi x = Q.front(); 38 Q.pop_front(); 39 for(int i = e[x.id]; i; i = edge[i].nex) { 40 int y = edge[i].v; 41 int len = edge[i].type == x.pre ? 0 : 1; 42 if(y == t) { 43 return x.dis + len; 44 } 45 if(mp[y][edge[i].type]) { 46 continue; 47 } 48 mp[y][edge[i].type] = 1; 49 if(len) { 50 Q.push_back(Poi(y, x.dis + 1, edge[i].type)); 51 } 52 else { 53 Q.push_front(Poi(y, x.dis, x.pre)); 54 } 55 } 56 } 57 return -1; 58 } 59 60 int main() { 61 int m, n; 62 scanf("%d%d", &n, &m); 63 for(int i = 1, x, y, z; i <= m; i++) { 64 scanf("%d%d%d", &x, &y, &z); 65 add(x, y, z); 66 add(y, x, z); 67 } 68 69 int t = BFS(1, n); 70 printf("%d", t); 71 72 return 0; 73 }