bzoj4398:福慧双修

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

#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]);
}
时间: 2024-10-13 13:57:45

bzoj4398:福慧双修的相关文章

bzoj4398: 福慧双修

正边权无向图,一条边两个方向权值不一定相同,求经过点1的最小简单环 简单环包含了点1的一条出边和一条入边,且这两条边不同,因此可以枚举这两条边的编号的二进制表示中哪一位不同,用最短路求此时的最优解,时间复杂度$O(mlog^2m)$ #include<bits/stdc++.h> using std::swap; using std::vector; using std::priority_queue; const int N=40007,inf=1000000000; int _(){ in

不会的图论题

列一下曾经做过的不会的图论题 bzoj4398: 福慧双修 bzoj4681: [Jsoi2010]旅行 NEERC 2017 Problem J Journey from Petersburg to Moscow 原文地址:https://www.cnblogs.com/tkandi/p/10556829.html

福慧双修(both)

福慧双修(both)题目描述:菩萨为行,福慧双修,智人得果,不忘其本.——唐·慧立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅氏如何福慧双修?被太后教导的甄嬛徘徊在御花园当中.突然,她发现御花园中的花朵全都是红色和蓝色的.她冥冥之中得到了响应:这就是指导她如何福慧双修的!现在御花园可以看作是有N块区域,M条小路,两块区域之间可通过小路连接起来.现在甄嬛站在1号区域,而她需要在御花园中绕一绕,且至少经过1个非1号区域的区域.但是恰好1号区域离碎玉轩最近,因此她最后还是要回到1

bzoj 4398 福慧双修 - 最短路

Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅氏如何福慧双修?被太后教导的甄嬛徘徊在御花园当中.突然,她发现御花园中的花朵全都是红色和蓝色的.她冥冥之中得到了响应:这就是指导她如何福慧双修的! 现在御花园可以看作是有N块区域,M条小路,两块区域之间可通过小路连接起来.现在甄嬛站在1号区域,而她需要在御花园中绕一绕,且至少经过1个非1号区 域的区域.但是恰好1号区域离碎玉轩最近,因此她最后还是要回到1号区

【BZOJ2407/4398】探险/福慧双修 最短路建模

[BZOJ2407]探险 Description 探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过! 比赛即将开始,工作人员说明了这次比赛的规则:每个溶洞和其他某些溶洞有暗道相连.两个溶洞之间可能有多条道路,也有可能没有,但没有一条暗道直接从自己连到自己.参赛者需要统一从一个大溶洞出发,并再次回到这个大溶洞. 如果就这么点限制,那么问题就太简单了,可是举办方又提出了一个条件:不能经过同一条暗道两次.这个条件让大家犯难

【视频+文字】刘素云老师:法雨惠群生--老实念佛不拐弯 今生一定到彼岸(附净空老法师点评)

刘素云老师 常念阿彌陀佛 2015-09-08 法雨惠群生 ——老实念佛不拐弯 今生一定到彼岸 2015年9月4日上午十点首播的<无量寿经科注第四回学习班>第165集 视频(建议WIFI下收看)   2015年9月4日上午十点首播的<无量寿经科注第四回学习班>第165集 从二O一四年五月到二O一五年五月,整整一年的时间,海贤老和尚的光碟我听(看)了两千遍.可能有的同修会说,不就是告诉念阿弥陀佛吗,用得着听(看)那么多遍吗?以我的切身体会,我的回答是,用得着,不但是用得着,而且是非常

《认识佛教》有声书-02-净空法师-初学佛课程(音)

说法狮子吼 2016-11-18 認識佛教有聲書02来自说法狮子吼00:0027:39 阿罗汉与辟支佛用的心,好像是水里的月亮,镜子里的月亮,叫镜花水月,都不是真的.从用心上看,菩萨的心跟佛的心很相似.很接近,是真的,不是假的:所以纵然是初住菩萨,刚刚破一品无明,证一分法身,他用的心就是真心,绝对没有虚妄,这叫‘正等正觉’.修学得到正等正觉,这个学位称为‘菩萨’.阿罗汉好比是学士,菩萨好比是硕士,佛好比是博士.所以‘佛’是通称,不是释迦牟尼佛一个人独称:任何人智慧达到究竟圆满,就是真心圆证,就称