zoukankan      html  css  js  c++  java
  • 7.9校内测T3,克鲁斯卡尔板子题

    题目背景

    lty 看着手机上播放的《Re:从零开始的异世界生活》,心中对ナツキ・スバル的厌恶值持续增加,对于レム、㍕的下场十分心痛,看到ナツキ・スバルペテルギウス・ロマネコンティ虐待,心中自然极爽。但男主ナツキ・スバル 是一个可以复活的奇男子,多次的死亡让他变得越发怠惰。ナツキ・スバル下定决心,为了让自己活得不那么累,以后连走路也要挑着短的走。

    题目描述

    一天,ナツキ・スバル 在无向花园中闲逛,想给エミリア 采几朵花,但是心中的怠惰作祟,决定走一条神奇的道路:

    • 起点为ss
    • 终点为tt
    • 满足在所有的可行道路中,当前所选道路上的最大的边权valval最小

    当然,怠惰的ナツキ・スバル 一点也不想动脑子,想让你在1s1s之内告诉他怎么走,否则他就会加入ペテルギウス・ロマネコンティ 的队伍,让剧情无法继续发展,限制你能用的内存为256MB256MB,请你帮帮他,来继续恶心lty的同时,让剧情顺利发展。

    输入格式

    第一行:nn ,mm共两个数,表示图有 nn个顶点,mm条边。

    第二至第m+1行:u_iuiv_iviw_iwi共三个数,表示边edge_iedgei的两个顶点分别是u_iuiv_ivi,边权为w_iwi

    第m+2行:sstt;共两个数,分别来表示道路的起点和终点

    输出格式

    一个数valval,表示道路上最大边权的最小值

    输入输出样例

    输入 #1
    4 4
    1 2 1
    2 4 4
    1 3 2
    3 4 3
    1 4
    输出 #1
    3

    说明/提示

    对于5050%的数据,满足 nleq100n100mleq2000m2000wleq100w100

    对于 100100%的数据,满足 nleq5000n5000mleq200000m200000wleq1000000w1000000

     

    克  鲁  斯  卡  尔  板  子  题

    然而我不会(芬芳)

    克鲁斯卡尔是一个最小生成树算法,运用贪心策略,找到最小边权和。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    using namespace std;
    const ll maxn=2e5+10;
    ll n,m,s,t;
    ll fa[maxn],eu,ev,ans,cnt;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    struct node
    {
        ll u,v,w;
    } edge[maxn];
    inline int find(ll x)
    {
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);//找祖先 
    }
    inline bool cmp(node a,node b)
    {
        return a.w<b.w;
    }//贪心思想,按边权排序,先连边权小的边 
    inline void kruskal()
    {
        sort(edge+1,edge+m+1,cmp); 
        for(int i=1;i<=m;i++)
        {
            eu=find(edge[i].u),ev=find(edge[i].v);//u是这条边的起点,v是这条边的终点 
            if(eu==ev) continue;//如果它们在一个集合里,那么不能连边 
            ans+=edge[i].w;//总长度加上边权 
            fa[ev]=eu;//合并祖先 (ev和eu倒过来没有影响) 
            cnt++;//边数++ 
            if(find(s)==find(t))//如果起点和终点已经在一个集合里了,那么输出 
            {
                printf("%lld
    ",edge[i].w);//因为我们是按边权排序之后逐渐加边,那么我们每次加的边一定比后来加的边边权小,本题要求的是路径中最大值最小,所以不用再往后找了,直接输出即可 
                return;
            }
            if(cnt==(n-1)) break;//如果边数==n-1,那说明已经把所有的点全部连起来了,直接break 
        }
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            scanf("%lld%lld%lld",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        s=read();
        t=read();
        kruskal();
        return 0;
    }
  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/57xmz/p/13278473.html
Copyright © 2011-2022 走看看