【2017.10.24】noip赛前集训 | T3 小D的旅途【最小环】
AC代码
T3 小D的旅途
【题目大意】
小 D 放假很喜欢宅在家里,可是一是因为小 D 宅得不够专业,二是因为 Z 国的假期实在是太多了,于是小 D 在家里呆不下去了,终于决定出去走走。 Z 国有 n 个城市和 m 条连接城市间的道路。一开始小 D 只是在 Z 国闲逛, 欣赏沿途的风景。然而当神奇的小 D 把整个国家都逛了一次以后,他突然发 现,神奇的 Z 国里每个城市都最多只有四条连着它的道路,且没有连接同一个 城市的道路。由于小 D 一直都向往一个方便快捷的世界,现在他想知道在 Z 国 中,从一个城市出发,最少走多长的路可以回到这个城市(出发城市可以由你 来决定)。
【数据范围】
对于 30%的数据,保证 1≤n≤8
对于 70%的数据,保证 1≤n≤200
对于 100%的数据,保证 1≤n≤1000,l≤10000
【题解】
①用 Floyd 在 dp 的时候记录一下最小环,自己测试是AC了。
②也可以考虑用 堆优化 + Dijkstra。
- 当两个点连通时,删除两点之间的边,然后跑一遍Dij。
- 本蒟蒻是按照点跑的,于是跑了 n2 遍 Dijstra, 也就是O(n2nlogn)妥妥地爆炸爆炸爆炸啊啊啊啊啊啊(怕是石乐志了摔!!!)。
- 其实只要跑 m 遍就好了(按边跑,每次选一条边删了,然后对它的两个端点跑Dijkstra)O(m*mlogm)。
————————————————————————————————————————————————————————————————
—————————————————————————————————————————————————————————————————
太弱了太弱了太弱了我,连个数组模拟指针都不会用,所以我研究了半天用指针该怎么开edge数组。。。。
啊啊啊啊啊啊啊啊啊还是去学数组模拟指针吧。


其实想着之前开一个数组标记一下如果这两个点找过的话,直接 continue 就好了。
本来想着这样和按边跑没什么区别了(。。。简直就是石乐志了。。果然弱爆了。。),然后就根据某数据发现这样子跑比按边跑多跑了一万两千一百多遍。。。。。
还是老老实实学数组模拟指针吧摔!

——————————————————————————————————————————————————————————
太弱了太弱了, 去看了数组模拟指针!!!!从下午调到放学!!漏洞百出啊艹
连把 std::make_pair(0, s) 写成了 std::make_pair(0, 0)都能调上半个多小时啊WTF!!!!!!!
以为我能A了的。。。。又出问题了。。。。。
___________________________________________10.25 __19:35__________________________________________
昨天没调完题就放学了,刚才重写了下,出了这个↓错误
漏了这个东西, WA了六个点... ...

好,A了终于... ...

#include <cstdio>
#include <queue>
#define Pair std::pair<int, int>
const int MAXN = 1e3 * 8 + 7;
int dist[MAXN], last[MAXN], num, n, m, st, end, minn = 0x7fffffff;
struct Edge {
int from, to, pow, next;
} edge[MAXN];
void addE(int x, int y, int z) {
++num;
edge[num].from = x;
edge[num].to = y;
edge[num].pow = z;
edge[num].next = last[x];
last[x] = num;
}
void Dij() {
std::priority_queue<Pair, std::vector<Pair>, std::greater<Pair> > q;
for (int i = 1; i <= n; i++) dist[i] = 0x7fffffff;
dist[st] = 0;
q.push(std::make_pair(0, st));
while (!q.empty()) {
Pair p = q.top();
q.pop();
int v = p.second;
if (dist[v] != p.first) continue;
for (int i = last[v]; i; i = edge[i].next) {
int e = edge[i].to;
if (v == st && e == end || v == end && e == end) continue;
if (dist[e] > dist[v] + edge[i].pow) dist[e] = dist[v] + edge[i].pow, q.push(std::make_pair(dist[e], e));
}
}
}
int main() {
// freopen("tour.in", "r", stdin);
// freopen("tour.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
addE(a, b, c);
addE(b, a, c);
}
for (int i = 1; i <= 2 * m; i += 2) {
st = edge[i].from;
end = edge[i].to;
Dij();
// printf("form %d to %d --> %d\n", st, end, dist[end]);
if (dist[end] == 0x7fffffff) continue;
if (minn > dist[end] + edge[i].pow) minn = dist[end] + edge[i].pow;
}
printf("%d\n", minn);
return 0;
}


浙公网安备 33010602011771号