Avito Cool Challenge 2018:D. Maximum Distance (最小生成树)

题目链接

题意 :

给出一个联通图和一些特殊的点,现在定义cost(u,v)为一条从u到v的路径上面边权的最大值 ,

定义dis(u,v) 为从u到v 路径上面cost 的最小值

然后求所有特殊点到其他特殊点的最大距离

题解:

做这题前,首先思考一件事情,对于一颗树来说点到点的距离是不是就是树上面路径的边权最大值

我们来证明一下:假设在最小生成树上面的路径cost为w1,另外在原图中还有一条路径从u到v,其cost为w2,那么必然有w2>w1的。那么我们最后的dis一定是w1。

那么我们现在的目标就是求特殊点到特殊点之间的最大距离。注意一下这里是从一个特殊点到其它所有特殊点的最大距离

我们根据Kruskal 算法的构建过程 , 在构建树的时候是先构造小的边的 , 所以我们就可以在Kruskal加边的时候更新答案 ,

我们假设现在有两个集合,现在将其连接起来,当满足两个集合里面都有特殊点时我们就可以更新答案了,否则就不行。

转载 现在还有一些问题没有解决 , 待后跟新

#include<bits/stdc++.h>
using namespace std;

const int maxn = 100001;//最大点数
int c[maxn], N,M,k;//并查集使用
int cnt;
bool a[maxn];
int VAL[maxn];
struct EDGE{
    int from, to, w;
    bool operator < (const EDGE &rhs) const{
        return this->w < rhs.w;
    };
}Edge[maxn];//储存边的信息,包括起点/终点/权值

inline void init()
{
    for(int i=0; i<=N; i++)
        c[i] = i;
    cnt = 0;
}

inline void AddEdge(int from, int to, int weight)
{
    Edge[cnt].from = from;
    Edge[cnt].to   = to;
    Edge[cnt].w    = weight;
    cnt++;
}

int Findset(int x)
{
    int root = x;
    while(c[root] != root)
        root = c[root];

    int idx;
    while(c[x] != root){ /// 路径压缩
        idx = c[x];
        c[x] = root;
        x = idx;
    }
    return root;
}

int Kruskal()//传入点数,返回最小生成树的权值,如果不连通返回-1
{
    sort(Edge,Edge+cnt);
    int EdgeCnt=0;//计算加入的边数
    int Cost=0;
     int MAX=0;
    for(int i=0;i<cnt;i++){
        int u=Edge[i].from;
        int v=Edge[i].to;
        int w=Edge[i].w;
        int R1 = Findset(u);
        int R2 = Findset(v);
        if(R1==R2) continue;
        c[R1]=R2;
        if(a[u]) VAL[R1]++;//标记的点
        if(a[v]) VAL[R2]++;
        if(VAL[R1] && VAL[R2] )//如果标记的点都有
        MAX=w;
       VAL[R2]+=VAL[R1];
        EdgeCnt++;
        if(EdgeCnt==N-1) break;
    }
    if(EdgeCnt<N-1) return -1;//不连通
    else return MAX;
}

int main()
{
        scanf("%d%d%d",&N,&M,&k);
        init();
        int Val;
        for(int i=1 ; i<=k ; i++)
        {
             scanf("%d",&Val);
             a[Val]=1;
        }

         for(int i=1 ; i<=M ; i++)
         {   int u,v,w;
             scanf("%d%d%d",&u,&v,&w);
             AddEdge(u,v,w);
         }
         int P=Kruskal();
         for(int i=1 ; i<=k ; i++)
         printf("%d ",P);
      //  printf("%d\n", Kruskal());

    return 0;
}

原文地址:https://www.cnblogs.com/shuaihui520/p/10136769.html

时间: 2024-09-30 12:40:57

Avito Cool Challenge 2018:D. Maximum Distance (最小生成树)的相关文章

Codeforces Avito Code Challenge 2018 D. Bookshelves

Codeforces Avito Code Challenge 2018 D. Bookshelves 题目连接: http://codeforces.com/contest/981/problem/D Description Mr Keks is a typical white-collar in Byteland. He has a bookshelf in his office with some books on it, each book has an integer positive

Avito Cool Challenge 2018 Solution

A. Definite Game 签. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int a; 7 while (scanf("%d", &a) != EOF) 8 { 9 [](int x) 10 { 11 for (int i = x - 1; i >= 1; --i) if (x % i) 12 { 13 printf("%d\n",

cf掉分记——Avito Code Challenge 2018

再次作死的打了一次cf的修仙比赛感觉有点迷.. 还好掉的分不多(原本就太低没法掉了QAQ) 把会做的前三道水题记录在这.. A: Antipalindrome emmmm...直接暴力枚举 code: //By Menteur_Hxy #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int n,ans; cha

[Avito Code Challenge 2018 G] Magic multisets(线段树)

题目链接:http://codeforces.com/contest/981/problem/G 题目大意: 有n个初始为空的‘魔法’可重集,向一个‘可重集’加入元素时,若该元素未出现过,则将其加入:否则该可重集中所有元素的个数都会翻倍. 例如将$2$加入${1,3}$会得到${1,2,3}$,将$2$加入${1,2,3,3}$会得到${1,1,2,2,3,3,3,3}$. $q$次操作,每次操作要么向一个区间内的所有可重集加入某个元素,要么询问一个区间内可重集的大小之和. $n,q ≤ 2×1

Avito Cool Challenge 2018 B - Farewell Party

题目大意: 有n个人 接下来一行n个数a[i] 表示第i个人描述其他人有a[i]个的帽子跟他不一样 帽子编号为1~n 如果所有的描述都是正确的 输出possible 再输出一行b[i] 表示第i个人的帽子的编号 如果存在矛盾 输出impossible 如果存在p 个人都描述有q个人跟他们的帽子不一样 此时若 p+q=n 说明正确且这p个人的帽子都一样 如 a[] = 3 3 2 2 2 ,此时一种解为 b[] = 1 1 2 2 2 存在p=2个人描述有q=3个人跟他们不一样 说明这两个人的帽子

Avito Cool Challenge 2018:C. Colorful Bricks

C. Colorful Bricks 题目链接:https://codeforces.com/contest/1081/problem/C 题意: 有n个横向方块,一共有m种颜色,然后有k个方块的颜色与其左边的颜色不同(第一个除外),问一共有多少染色方案. 题解: 我们首先来考虑一下dp. 设dp(i,j)为当前第i个方块,一共有j个方块与它前面的方块不同的方案个数. 那么转移方程为dp(i,j)=dp(i-1,j-1)*(m-1)+dp(i-1,j). 代码如下: #include <bits

Avito Cool Challenge 2018 A. B题解

A. Definite Game 题目链接:https://codeforces.com/contest/1081/problem/A 题意: 给出一个数v,然后让你可以重复多次减去一个数d,满足v%d!=0,问最后可以得到最小的是多少. 题解: 除开v=2输出2,其余直接输出1就行了= =/ 代码如下: #include <bits/stdc++.h> using namespace std; int main(){ int v; cin>>v; cout<<(v==

Leetcode - 624 - Maximum Distance in Arrays

624. Maximum Distance in Arrays Given m arrays, and each array is sorted in ascending order. Now you can pick up two integers from two different arrays (each array picks one) and calculate the distance. We define the distance between two integers a a

LeetCode Maximum Distance in Arrays

原题链接在这里:https://leetcode.com/problems/maximum-distance-in-arrays/description/ 题目: Given m arrays, and each array is sorted in ascending order. Now you can pick up two integers from two different arrays (each array picks one) and calculate the distanc