zoukankan      html  css  js  c++  java
  • [MST]JZOJ 3237 间谍派遣

    Description

     你是M,一个雇佣N个标号为从1到N的间谍的情报机关的总管。每个间谍被派往不同的国家并在那获取重要情报。

     如下是你的任务:

        1.在部分间谍间组织会面。每次会面在两个间谍间进行,两个间谍交换他们自己获取的或从之前会面中得到的信息。因为在不同国家的两个间谍间组织机密会面很困难,所以每次秘密会面都有一个费用。

        2.当所有会面结束后,选择一部分间谍参加拯救世界的任务。一个间谍k参加此项任务需要花费Mk。很重要的一点是,任务要成功,必须满足参加任务的间谍获取的情报聚集到一起包含了其他剩余间谍所有的信息。

     请找出完成任务的最小花费,即组织会面和派遣间谍的费用之和。
     

    Input

    输入的第一行包含正整数N,表示间谍数目(2≤N≤1000)。

    接下来的N行包含N个不超过10^6的非负整数。在k行m列的数字表示间谍k和m间会面的花费,同样的,与m行k列的数字相等,k=m时数字为0。

    接下来的一行包含N个正整数Mk(1≤Mk≤10^6),分别为派遣间谍1,2,…,N参加任务的花费。

    Output

    只有一行,为所需的最小总费用。
     

    Sample Input

    输入1:
    3
    0 6 9
    6 0 4
    9 4 0
    7 7 7

    输入2:
    3
    0 17 20
    17 0 10
    20 10 0
    15 9 12

    输入3:
    5
    0 3 12 15 11
    3 0 14 3 20
    12 14 0 11 7
    15 3 11 0 15
    11 20 7 15 0
    5 10 10 10 10
     

    Sample Output

    输出1:
    17

    输出2:
    34

    输出3:
    28
     

    Data Constraint

    40%的数据满足N<=30且存在最多不超过4个间谍参加任务的最优方案;

    50%的数据满足派遣每个间谍参加任务的费用是一样的。
     

    Hint

    样例1:将会在1和2,接着2和3间谍间举行会面,然后送间谍2参与任务。

    样例2:将会在2和3间谍间举行会面,然后送间谍1和2参与任务。

    样例3:将会在2和4,接着1和2,接着3和5间谍间举行会面,然后送间谍1和3(或1和5)参与任务。

    分析

    考场上我居然有会做的题*2

    MST随便搞搞,合并的时候判断一下是单独提出来代价高还是合并再提代价高,如果一样优先合并(贪心性显然)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=1e3+10;
    const int Inf=2147483647;
    struct Graph {
        int u,v,w;
        friend bool operator < (Graph a,Graph b) {
            return a.w<b.w;
        }
    }g[N*N/2];
    int cnt;
    int f[N],m[N],cost[N];
    bool vis[N];
    int n,ans;
    
    int Get_F(int x) {return x==f[x]?x:f[x]=Get_F(f[x]);}
    
    int main() {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            for (int j=1,a;j<=n;j++) {
                scanf("%d",&a);
                if (j<i) g[++cnt]=(Graph){i,j,a};
            }
        sort(g+1,g+cnt+1);
        for (int i=1;i<=n;i++) scanf("%d",&m[i]),f[i]=i;
        for (int i=1,u,v;i<=cnt;i++)
            if ((u=Get_F(g[i].u))!=(v=Get_F(g[i].v))) {
                if (g[i].w+min(m[u],m[v])>m[u]+m[v]) continue;
                ans+=g[i].w;
                f[u]=v;m[v]=min(m[u],m[v]);
            }
        for (int i=1,u;i<=n;i++)
            if (!vis[u=Get_F(i)]) {
                ans+=m[u];
                vis[u]=1;
            }
        printf("%d",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/mastervan/p/11178350.html
Copyright © 2011-2022 走看看