AtCoder arc061C Snuke's Subway Trip

时间:2023-03-09 07:06:12
AtCoder arc061C Snuke's Subway Trip

大意:

给你一张无向图,边有种类。

当你第一次/重新进入某种边时费用 + 1

在同一种边之间行走无费用。

求 1 到 n 的最小费用。

嗯...乍一看有一个很直观的想法:记录每个点的最短路的上一条边的种类。

但是这个算法是个错的......有些数据能够hack掉。

由于边权只有0 & 1,考虑01BFS。

事实上我们还要记录每个点来之前的边,然后就要写结构体/pair

然后还要判重...

正解:考虑按照每个点的边的type拆点。
在不同点的同一type分点之间边权为0
原点与拆出来的点之间边权为1
然后跑01BFS即可。

开n个map来存点的分点编号。
map 的 count 用法(虽然没啥卵用)

我照着正解写了个过了,然后写了自己的想法就WA.....

不知道为什么。对拍可能生成的数据太弱了,全是符合的。

 #include <cstdio>
#include <map>
#include <deque> const int N = ; int cnt; std::map<int, int> mp[N]; struct Edge {
int v, nex, len;
}edge[N << ]; int top; int e[N], dis[N], vis[N]; inline int get(int x, int type, int &f) {
if(mp[x][type]) {
f = ;
return mp[x][type];
}
f = ;
return mp[x][type] = ++cnt;
} inline void add(int x, int y, int z) {
++top;
edge[top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top++;
edge[top].v = x;
edge[top].len = z;
edge[top].nex = e[y];
e[y] = top;
return;
} inline int BFS(int s, int t) {
vis[s] = ;
dis[s] = ;
std::deque<int> Q;
Q.push_back(s);
while(!Q.empty()) {
int x = Q.front();
Q.pop_front();
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(vis[y]) {
continue;
}
dis[y] = dis[x] + edge[i].len;
if(y == t) { /// error : y == s
return dis[y];
}
vis[y] = ;
if(edge[i].len) {
Q.push_back(y);
}
else {
Q.push_front(y);
}
}
}
return -;
} int main() {
freopen("in.in", "r", stdin);
freopen("my.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
cnt = n;
for(int i = , x, y, z, f; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
int x_type = get(x, z, f);
if(f) {
add(x, x_type, );
}
int y_type = get(y, z, f);
if(f) {
add(y, y_type, );
}
add(x_type, y_type, );
} int ans = BFS(, n);
printf("%d", ans >> ); return ;
}

AC代码

 #include <cstdio>
#include <map>
#include <deque> const int N = ; std::map<int, int> mp[N]; struct Edge {
int v, nex, type;
}edge[N << ]; int top; int e[N]; inline void add(int x, int y, int z) {
top++;
edge[top].v = y;
edge[top].type = z;
edge[top].nex = e[x];
e[x] = top;
return;
} struct Poi {
int id, dis, pre;
Poi(int id, int dis, int pre) {
this->id = id;
this->dis = dis;
this->pre = pre;
}
}; inline int BFS(int s, int t) {
std::deque<Poi> Q;
Q.push_back(Poi(s, , ));
while(!Q.empty()) {
Poi x = Q.front();
Q.pop_front();
for(int i = e[x.id]; i; i = edge[i].nex) {
int y = edge[i].v;
int len = edge[i].type == x.pre ? : ;
if(y == t) {
return x.dis + len;
}
if(mp[y][edge[i].type]) {
continue;
}
mp[y][edge[i].type] = ;
if(len) {
Q.push_back(Poi(y, x.dis + , edge[i].type));
}
else {
Q.push_front(Poi(y, x.dis, x.pre));
}
}
}
return -;
} int main() {
int m, n;
scanf("%d%d", &n, &m);
for(int i = , x, y, z; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
} int t = BFS(, n);
printf("%d", t); return ;
}

WA代码