zoukankan      html  css  js  c++  java
  • [20200721NOIP提高组模拟T3]最小代价

    题目大意:

      给你n个点$(nleq100000)$所构成的边带权的无向图,每个点都有黑或白两种颜色之一,其中黑记为1,白记为0.现在要你选择一些边(选择一条边的代价即为此边权值),用这些边构成新的图,使得新图中每个白点都与黑点联通,且每个白点到距离其最近的黑点的距离等于原图中的最短距离.若不存在这样的图,输出impossible.

    solution:

      这题蛮神奇的,思路也不错,让我们来分析分析.首先,要求出每个白点到其最近的黑点的最短距离,我们可以通过新建一个超级点T,与每个黑点相连且边权为0.SPFA求出最短距离,然后想办法构图.我们来分析一下白点:对于一个白点$x$,加入到其最近的黑点与其直接相连,那直接将边权统计进去;加入这个白点与其它白点$y$相连,那白点y到黑点的最短路径一定是白点x到黑点的最短路径的子集,且仅差一条边,这条边将点$x$与$y$相连,所以只需将此边计入ans,因为其余路径点$y$可以统计.

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define R register
    #define next exntttttttttttttttttttttt
    #define debug puts("mlg")
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writesp(ll x);
    inline void writeln(ll x);
    ll n,m,T;
    ll col[200000];
    ll From[500000],to[500000],head[500000],tot=1,c[500000],next[500000];
    inline void add(ll x,ll y,ll z){
        to[++tot]=y;From[tot]=x;next[tot]=head[x];head[x]=tot;c[tot]=z;
    }
    ll d[500000],pre[500000],last[500000];
    queue<ll>q;
    bool vis[500000];
    inline void spfa(){
        memset(d,0x3f,sizeof d);
        d[T]=0;q.push(T);
        while(q.size()){
            ll x=q.front();q.pop();vis[x]=false;
            for(R ll i=head[x],ver;i;i=next[i]){
                ver=to[i];
                if(d[ver]>d[x]+c[i]){
                    d[ver]=d[x]+c[i];
                    pre[ver]=x;
                    last[ver]=i;
                    if(!vis[ver]){
                        q.push(ver);
                        vis[ver]=true;
                    }
                }
            }
        }
    }
    ll ans;
    int main(){
        n=read();m=read();T=n+1;
        for(R ll i=1;i<=n;i++){
            col[i]=read();
            if(col[i]){add(i,T,0);add(T,i,0);}
        }
        for(R ll i=1,x,y,z;i<=m;i++){
            x=read();y=read();z=read();
            if(x==y) continue;
            add(x,y,z);add(y,x,z);
        }
        spfa();
        for(R ll i=1;i<=n;i++)if(!col[i]&&d[i]==d[0]){puts("impossible");return 0;}
        for(R ll x=1;x<=n;x++){
            if(col[x]) continue;
            ans+=c[last[x]];
        }
        writeln(ans);
    }
    inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
    inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
    inline void writesp(ll x){write(x);putchar(' ');}
    inline void writeln(ll x){write(x);putchar('
    ');}
  • 相关阅读:
    开发中常用js记录(二)
    c# 我所理解的 值类型 and 引用类型
    c# 枚举
    ModelState.IsValid总为false原因
    学习总结 之 WebApi服务监控 log4net记录监控日志
    How to Deinstall Oracle Clusterware Home Manually
    oracle client 低于 oracle server 端,导致报错ORA-01882
    转 zabbix 用户建立和中文化
    转 rman 恢复报错
    10g 升级到11g 失效对象2则
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13361620.html
Copyright © 2011-2022 走看看