• Codeforces Round #212 (Div. 2) D. Fools and Foolproof Roads


    我猜是哈夫曼算法。。。即贪心把当前连通分量集合中权值最小的两个连接起来,再合成一个加入集合,迭代下去。

    来不及交了,先贴下代码。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<queue>
    #include<string>
    #include<cmath>
    #include<fstream>
    #include<iomanip>
    
    using namespace std;
    
    #define LL long long
    #define MAXN 111111
    int n, m, u[MAXN], v[MAXN], w[MAXN];
    int p, q, f[MAXN<<1];
    LL fw[MAXN<<1];
    
    int finds(int x){
        if(f[x] == -1) return x;
        else return (f[x] = finds(f[x]));
    }
    #define cint const int
    #define inf 1e15
    
    bool cmp(cint a, cint b){
        return fw[a] < fw[b];
    }
    
    int t[MAXN], ans1[MAXN], ans2[MAXN];
    queue<int> ori, noi;
    
    bool have(int &n1, int &n2){
        bool f = false;
        int q1=-1, q11=-1, q2=-1, q22=-1;
        if(!ori.empty()){
            q1 = ori.front();  ori.pop();
            if(!ori.empty()) q11 = ori.front();
        }
        if(!noi.empty()){
            q1 = noi.front();   noi.pop();
            if(!noi.empty()) q22 = noi.front();
        }
        if(q1<0 || q2<0) return false;
        LL a1 = fw[q1] + fw[q2], a2 = (q11 > -1 ? fw[q1]+fw[q11] : inf),
           a3 = (q22 > -1 ? fw[q2] + fw[q22] : inf);
        LL mn = min(min(a1, a2), a3);
        if(a1 == mn){
            n1 = q1;
            n2 = q2;
    
        }
        else if(a2 == mn){
            ori.pop();  n1=q1;  n2=q11;
        }
        else{
            noi.pop();  n1=q2;  n2=q22;
        }
        return true;
    }
    
    int mp[MAXN<<1];
    void getans(int cnt){
        int i, j=0;
        for(i=1; i<=n; i++) if(f[i]==-1)
            t[j++] = i;
        sort(t, t+j, cmp);
        int mx = n + 1;
        while(!ori.empty()) ori.pop();      while(!noi.empty()) noi.pop();
        for(i=0; i<cnt; i++) ori.push(t[i]);
        for(i=0; cnt>q && p;){
            int n1, n2;
            if(have(n1, n2)){
                f[n1] = n2;
                LL t1 = (fw[n2] + fw[n1]) * 2 + 1, t2 = 1e9;
                fw[n2] = min(t1, t2);
                fw[mx] = fw[n2];
                mp[mx] = n2;
                noi.push(mx);
                if(n1 > n) n1 = mp[n1];
                if(n2 > n) n2 = mp[n2];
                ans1[i] = n1, ans2[i] = n2;
                cnt--;    i++;
                p--;        mx++;
            }
            else break;
        }
        if(p){
            int a1=-1, a2=-1;
            for(j=1; j<=n; j++) if(f[j]>-1){
                if(a1==-1) a1=j;
                else{ a2=j; break;}
            }
            while(p--)  ans1[i]=a1, ans2[i++]=a2;
        }
        for(j=0; j<i; j++) printf("%d %d
    ", ans1[j], ans2[j]);
    }
    
    int main(){
        //freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        while(scanf(" %d %d %d %d", &n, &m, &p, &q)==4){
            int i, j, cnt = n;
            for(i=0; i<m; i++) scanf(" %d %d %d", &u[i], &v[i], &w[i]);
            fill_n(f, n<<1, -1);
            fill_n(fw, n+1, 0);
            for(i=0; i<m; i++){
                int x = finds(u[i]), y = finds(v[i]);
                if(x != y){
                    f[x] = y;
                    fw[y]+=w[i];
                    cnt--;
                }
            }
            if(cnt < q || cnt - p > q || (cnt==n && q==n && p)){
                printf("NO
    ");     continue;
            }
            printf("YES
    ");
            getans(cnt);
        }
        return 0;
    }
    
  • 相关阅读:
    2018北美部分CS项目学费
    APP接口自动化测试JAVA+TestNG(二)之TestNG简介与基础实例
    浅谈MITM攻击之信息窃取(解密315晚会报道的免费WIFI窃取个人信息)
    APP接口自动化测试JAVA+TestNG(一)之框架环境搭建
    Android测试提升效率批处理脚本(二)
    Android APP压力测试(三)之Monkey日志自动分析脚本
    Android系统build.prop文件
    Android APP压力测试(二)之Monkey信息自动收集脚本
    Android APP压力测试(一)之Monkey工具介绍
    Android反编译(三)之重签名
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3424592.html
Copyright © 2020-2023  润新知