zoukankan      html  css  js  c++  java
  • 刷题总结——逐个击破(洛谷2700)

    题目:

    题目背景

    三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,***制定了先切断敌人东西两头退路然后再逐个歼灭敌人的战略方针。秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面。

    题目描述

    现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。

    输入输出格式

    输入格式:

    第一行包含两个正整数n和k。

    第二行包含k个整数,表示哪个城市别敌军占领。

    接下来n-1行,每行包含三个正整数a,b,c,表示从a城市到b城市有一条公路,以及破坏的代价c。城市的编号从0开始。

    输出格式:

    输出一行一个整数,表示最少花费的代价。

    输入输出样例

    输入样例#1: 复制
    5 3
    1 2 4
    1 0 4
    1 3 8
    2 1 1
    2 4 3
    输出样例#1: 复制
    4

    说明

    【数据范围】

    10%的数据:2≤n≤10;

    100%的数据:2≤n≤100000,2≤k≤n,1≤c≤1000000。

    题解:

      首先换个思维考虑:我们该保留哪些边?

      容易想到最大生成森林···最后保留的边的总和越大删除的就越小···

      将边从大到小排序后判下两边的点集中是否有特殊点即可···

      然而脑子进水刚开始想的时候没有想到并查集··只用在合并的时候让特殊点作为祖先即可·

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    struct node{int x,y,v;}ed[N];
    int n,m,father[N];
    bool jud[N];
    inline int R(){
        char c;int f=0;
        for(c=getchar();c<'0'||c>'9';c=getchar());
        for(;c<='9'&&c>='0';c=getchar())    f=(f<<3)+(f<<1)+c-'0';
        return f;
    }
    bool cmp(node a,node b){return a.v>b.v;}
    inline int get(int a){return father[a]==a?a:(father[a]=get(father[a]));}
    inline void comb(int a,int b){
        int fa=get(a),fb=get(b);
        if(!jud[fa]&&jud[fb])    father[fa]=fb;
        else father[fb]=fa;
    }
    int main(){
        //freopen("a.in","r",stdin);
        n=R(),m=R();int a;
        for(int i=1;i<=m;i++)    a=R(),jud[a]=true;
        for(int i=1;i<n;i++){
            ed[i].x=R(),ed[i].y=R(),ed[i].v=R();
        }
        sort(ed+1,ed+n,cmp);long long ans=0;
        for(int i=1;i<=n;i++)    father[i]=i;
        for(int i=1;i<n;i++){
            int x=ed[i].x,y=ed[i].y,v=ed[i].v;
            if(jud[get(x)]&&jud[get(y)]){
                ans+=v;
            }
            else  comb(x,y);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    JS-Array数组对象
    JS-Math对象
    JS-Date对象
    JS-流程控制汇集
    css笔记
    CSS3-box盒布局
    css笔记
    CSS3中的animation动画
    JS-百钱买百鸡案例-for循环制作
    JS-用js的for循环实现九九乘法表以及其他算数题等
  • 原文地址:https://www.cnblogs.com/AseanA/p/7767113.html
Copyright © 2011-2022 走看看