【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(nnlogn)妥妥地爆炸爆炸爆炸啊啊啊啊啊啊(怕是石乐志了摔!!!)。
  • 其实只要跑 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;
}
AC代码

 

 

posted @ 2017-10-25 19:42  E-Valley  阅读(195)  评论(0)    收藏  举报