• NOI2003 逃学的小孩


    题目链接 https://www.luogu.com.cn/problem/P4408

    分析

    这好像很裸的样子,题目说了一堆废话,最后其实就是让求三个点,使得(AB+BC)最小,感性的理解蒙一下,应该有一条边是直径,不然把任意一条边换成直径都可以使答案更优,然后就找直径呗,找完直径枚举直径两端点到其他点的距离,最后答案为直径长+(max(min(dis1,dis2))),好像就水过这道题了?
    由于它是个树,所以根据某学长的理论,随便跑都可以,我dfs忘记咋写的了,想练一下spfa来,毕竟我那个不熟,但看了看时间太晚了就打了一个dij,没想到真的过了。。。证明的话明天心情好再补吧

    #include<iostream>
    #include<queue>
    #define ll long long 
    using namespace std;
    const int N=2e5+10;
    struct Edge{
        int to,nxt;
        ll val;
    }e[N<<1];
    struct Node{
        int id;ll val;
        Node(){}
        Node(int a,ll b){id=a,val=b;}
        bool operator <(const Node&A)const {
            return val>A.val;
        }
    };
    int Head[N],len;
    void Ins(int a,int b,ll c){
        e[++len].to=b;e[len].val=c;
        e[len].nxt=Head[a];Head[a]=len;
    }
    int n;bool inq[N];
    ll dis1[N],dis2[N];
    int dij(int s,ll dis[N]){
        for(int i=1;i<=n;i++){
            dis[i]=1e17;
            inq[i]=0;
        }
        dis[s]=0;inq[s]=1;
        priority_queue<Node> q;q.push(Node(s,0));
        while(!q.empty()){
            Node u=q.top();q.pop();inq[u.id]=0;
            for(int i=Head[u.id];i;i=e[i].nxt){
                int v=e[i].to;
                if(inq[v])continue;
                inq[v]=1;
                if(dis[v]>dis[u.id]+e[i].val){
                    dis[v]=dis[u.id]+e[i].val;
                    q.push(Node(v,dis[v]));
                }
            }
        }
        ll Max=0;int id=0;
        for(int i=1;i<=n;i++)
            if(dis[i]>Max)Max=dis[i],id=i;
        return id;
    }
    int main(){
        ios::sync_with_stdio(false);
        int m;
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            int a,b;ll c;
            cin>>a>>b>>c;
            Ins(a,b,c);Ins(b,a,c);
        }
        int a=dij(1,dis1);
        int b=dij(a,dis2);
        dij(b,dis1);
        ll Max=0;
        for(int i=1;i<=n;i++)
            Max=max(Max,min(dis1[i],dis2[i]));
        cout<<dis2[b]+Max;
    }
    
    

    Tips:

    你会发现我在函数里写的是手动赋值,为啥不(memset)呢,这里用(memset)的话会出问题,又可能要问了,之前跑最短路用没出过问题啊,但这里是不一样的,这里是对传进来的一个数组进行复制,(memset)本身没有问题,问题出在(size of)上,(size of)的处理时间的在编译期,也就是说对于动态生成的数组大小是不能用(sizeof)来算出来的。因为如果传到函数里,数组会退化成指针,于是(size of)就返回了指针的大小,这显然不是我们想要的,解决问题的办法有两个。一是像我那样,二是因为每次传的(dis)数组大小一样,直接写(size of dis1),这样编译器就可以确定我们(size of)的大小了。

  • 相关阅读:
    linux入门_韩顺平_复习版_用户管理
    linux入门_韩顺平_复习版_开启、重启、用户登陆注销
    python入门_老男孩_列表的增删查改
    git入门_尚硅谷_git简介
    码农要求_python豆瓣_2018校招
    python入门_老男孩_数据类型简介_int/bool/str转换_字符串索引和切片_字符串操作_day3
    LeetCode--链表3-经典问题
    LeetCode--链表2-双指针问题
    LeetCode--链表1-单链表
    LeetCode---二叉树3-总结例题
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12663882.html
Copyright © 2020-2023  润新知