码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4398:福慧双修

时间:2017-01-07 00:32:39      阅读:314      评论:0      收藏:0      [点我收藏+]

标签:turn   blog   scanf   struct   std   namespace   com   break   c++   

学习了一下最短路的姿势,这个建图方法好妙啊,虽然不会证明正确性……

#include <bits/stdc++.h>
#define N 220000
#define INF 1000000000
using namespace std;
int n, m;
int ai[N], bi[N], ci[N], di[N];
int check;
class DIJ
{
private:
    struct node {int t, d;};
    struct comp {int operator () (node a, node b) {return a.d > b.d;}};
    priority_queue <node, vector <node>, comp> Q;
public:
    vector <int> bi[N], ci[N];
    int dis[N], vis[N], pre[N];
    int tot;
    void build(int a, int b, int c)
    {
        bi[a].push_back(b); ci[a].push_back(c);
        //if (check) printf("%d %d %d\n",a,b,c);  
    }
    void solve()
    {
        for (int i = 2; i <= tot; ++ i) dis[i] = INF, vis[i] = 0;
        dis[1] = vis[1] = 0;
        Q.push((node){1, 0});
        while (!Q.empty())
        {
            int hd;
            do hd = Q.top().t, Q.pop();
            while (vis[hd] && !Q.empty());
            if (vis[hd]) break; else vis[hd] = 1;
            for (int j = 0; j < bi[hd].size(); ++ j)
                if (dis[hd] + ci[hd][j] < dis[bi[hd][j]])
                {
                    dis[bi[hd][j]] = dis[hd] + ci[hd][j];
                    pre[bi[hd][j]] = hd == 1? bi[hd][j]: pre[hd];
                    Q.push((node){bi[hd][j], dis[bi[hd][j]]});
                }
        }
    }
} A, B;
int tot, ans = INF, bac = INF, pp;
int main()
{
    scanf("%d%d", &n, &m); A.tot = n; B.tot = n + 1;
    for (int i = 1; i <= m; ++ i) 
    {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        tot ++; ai[tot] = a; bi[tot] = b; ci[tot] = c;
        tot ++; ai[tot] = b; bi[tot] = a; ci[tot] = d;
        A.build(a, b, c);
        A.build(b, a, d);
        if (a == 1 || b == 1) if (bac > c + d) bac = c + d, pp = (a == 1? b: a);
    }
    A.solve();
    A.dis[1] = bac; A.pre[1] = pp;
    check = 1;
    for (int i = 1; i <= tot; ++ i)
    {
        if (ai[i] == 1)
        {
            if (A.pre[bi[i]] != bi[i])
                B.build(1, bi[i], ci[i]);
        }
        else if (bi[i] == 1)
        {
            if (A.pre[ai[i]] != ai[i])
                B.build(1, n + 1, A.dis[ai[i]] + ci[i]);
            else B.build(ai[i], n + 1, ci[i]);
        }
        else if (A.pre[ai[i]] != A.pre[bi[i]])
            B.build(1, bi[i], A.dis[ai[i]] + ci[i]);
        else B.build(ai[i], bi[i], ci[i]);
    }
    B.solve();
    printf("%d\n", B.dis[n + 1]);
}

 

bzoj4398:福慧双修

标签:turn   blog   scanf   struct   std   namespace   com   break   c++   

原文地址:http://www.cnblogs.com/AwD-/p/6257803.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!