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%的数据,满足 n\leq100n100m\leq2000m2000w\leq100w100

对于 100100%的数据,满足 n\leq5000n5000m\leq200000m200000w\leq1000000w1000000

 

克  鲁  斯  卡  尔  板  子  题

然而我不会(芬芳)

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

代码:

#include
#include
#include
#include
#include
#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\n",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;
}

你可能感兴趣的:(7.9校内测T3,克鲁斯卡尔板子题)