zoukankan      html  css  js  c++  java
  • 【NOIP2015模拟10.22】最小代价

    Description
    给出一幅由n个点m条边构成的无向带权图。
    其中有些点是黑点,其他点是白点。
    现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个黑点,可以选取其中任意一个),我们想要使得花费的代价最小。请问这个最小代价是多少?
    注意:最后选出的边保证每个白点到离它最近的黑点的距离仍然等于原图中的最短距离。

    Input
    第一行两个整数n,m;
    第二行n 个整数,0表示白点,1 表示黑点;
    接下来m 行,每行三个整数x,y,z,表示一条连接x和y 点,权值为z 的边。

    Output
    如果无解,输出impossible;
    否则,输出最小代价。

    Sample Input
    5 7
    0 1 0 1 0
    1 2 11
    1 3 1
    1 5 17
    2 3 1
    3 5 18
    4 5 3
    2 4 5

    Sample Output
    5
    【样例解释】
    选 2、4、6三条边

    Data Constraint
    对30%的输入数据: 1≤n≤10, 1≤m≤20;
    对100%的输入数据:1≤n≤100000,1≤m≤200000,1≤z≤1000000000
    .
    .
    .
    .
    .

    分析

    这里写图片描述
    .
    .
    .
    .
    .

    程序:
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    struct edge 
    {
        long long to,from,v; 
    }e[600001],k[600001];
    queue<int>q;
    int inf=0x3f3f3f;
    long long d[100001],ans,fa[100001],n,m,head[100001],c,t;
    bool f[100001];
    
    void spfa()
    {
        memset(d,inf,sizeof(d));
        memset(f,false,sizeof(f));
        q.push(0); 
        d[0]=0;
        while (!q.empty())
        {
            int u=q.front(); 
            q.pop();
            f[u]=false;
            for (int i=head[u];i;i=e[i].from)
            if (d[u]+e[i].v<d[e[i].to])
            {
                d[e[i].to]=d[u]+e[i].v;
                if (!f[e[i].to])
                {
                    q.push(e[i].to);
                    f[e[i].to]=true;
                }
            }
        }
    }
    
    void dg(int x)
    {
        for (long long i=head[x];i;i=e[i].from)
        if (d[x]+e[i].v==d[e[i].to])
        {
            dg(e[i].to);
            k[++t].from=x;k[t].to=e[i].to;k[t].v=e[i].v;
        }
    }
    
    long long getfather(int x)
    {
        if (fa[x]==x) return x;
        return fa[x]=getfather(fa[x]);
    }
    
    void work()
    {
        for (int i=1;i<=n;i++) 
        fa[i]=i;
        for (long long i=1;i<=t;i++)
        {
            long long x=getfather(k[i].from),y=getfather(k[i].to);
            if (x!=y)
            {
                ans+=k[i].v;
                fa[y]=x;
            }
        }
    }
    
    bool cmp(edge x,edge y) 
    { 
        return x.from<y.from; 
    }
    
    void add(int x,int y,int z) 
    { 
        e[++c].to=y; 
        e[c].from=head[x]; 
        e[c].v=z; 
        head[x]=c; 
    }
    
    int main()
    {
        cin>>n>>m;
        for (int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            if (x==1) add(0,i,0);
        }
        for (int i=1;i<=m;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            add(x,y,z); 
            add(y,x,z);
        }
        spfa();
        dg(0);
        sort(k+1,k+t+1,cmp);
        work();
        if (ans==0) cout<<"impossible"; else cout<<ans;
    }
  • 相关阅读:
    Lucene 全文检索入门
    Elastic Stack 笔记(九)Elasticsearch5.6 集群管理
    Elastic Stack 笔记(八)Elasticsearch5.6 Java API
    Elastic Stack 笔记(七)Elasticsearch5.6 聚合分析
    Elastic Stack 笔记(六)Elasticsearch5.6 搜索详解
    Elastic Stack 笔记(五)Elasticsearch5.6 Mappings 映射
    JAVA中的static
    类继承和初始化类的执行顺序
    java继承 初始化顺序
    分析java类的初始化契机
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499928.html
Copyright © 2011-2022 走看看