zoukankan      html  css  js  c++  java
  • 【NOIP模拟】黑白图

    题面

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

    分析

    这道题考的时候写的比较久,结果思路完全错误..看着黑白就觉得像一道叫位图的题,问的是每个黑点到白点的距离,做法是将所有白点同时扩展,但是那是个无权图啊,我抖机灵如法炮制,挂到窒息。

    看到正解不是很意外,核心思想就是加了一个超级源。

    因为此题的难度在于如何处理多源最短路。将超级源和每个黑点连一条权值为0的边,以超级源为起点跑spfa或者dijstra,就能等效得出白点到最近的黑点的距离了。

    统计这些在最近路径上的边只需要遍历一遍,显然,满足d[u]+w==d[v]的边就在最短路径上,再将这些边抽出来,在新图上跑最小生成树。

    因为无论留下的道路是哪一条,对于任意白点,只要能到达黑点,那一定是最短的,因为我们本来留下的边就是最短路径。最小生成树能保证图的连通,并更优化边集的选择。所以就是两个板套在一起,就看能不能想到了。。

    注意long long

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100010
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ll long long
    ll n,m,cnt=0,cot=0,num=0,ans=0,sup=0;
    ll first[N],col[N],fa[N],d[N],black[N],vis[N];
    struct email
    {
        ll u,v,w;
        ll nxt;
    }e[N*5],a[N*5];
    queue<ll>q;
    inline ll find(ll x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    bool cmp(email a,email b)
    {
        return a.w<b.w;
    }
    
    inline void add(ll u ,ll v,ll w)
    {
        e[++cnt].nxt=first[u];first[u]=cnt;
        e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
    }
    
    inline void rebuild(ll u ,ll v,ll w)
    {
        a[++cot].u=u;a[cot].v=v;a[cot].w=w;
    }
    
    void spfa(ll x)
    {
        q.push(x);vis[x]=1;d[x]=0;
        while(!q.empty())
        {
            ll u=q.front();q.pop();vis[u]=0;
            for(ll i=first[u];i;i=e[i].nxt)
            {
                ll v=e[i].v,w=e[i].w;
                if(d[v]>d[u]+w)
                {
                    d[v]=d[u]+w;
                    if(!vis[v])
                    {
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    void kruskal()
    {
        for(ll i=1;i<=n;i++)
            fa[i]=i;
        sort(a+1,a+1+cot,cmp);
        for(ll i=1;i<=cot;i++)
        {
            ll u=a[i].u,v=a[i].v,w=a[i].w;
            ll fax=find(u),fay=find(v);
            if(fax!=fay)
            {
                fa[fax]=fay;
                ans+=w;num++;
            }
            if(num==n-1)
                break;
        }
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld",&col[i]);
            if(col[i])add(sup,i,0);
            d[i]=INF;
        }    
        for(ll i=1;i<=m;i++)
        {
            ll u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        spfa(sup);
        for(ll i=1;i<=n;i++)
            if(d[i]==INF)
            {
                printf("impossible
    ");
                return 0;
            }
        for(ll i=1;i<=n;i++)
            for(ll p=first[i];p;p=e[p].nxt)
            if(e[p].w+d[i]==d[e[p].v])
                rebuild(e[p].u,e[p].v,e[p].w);        
        kruskal();
        printf("%lld
    ",ans);
        return 0;
    }
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    从狄利克雷卷积到莫比乌斯函数
    Codeforces Round #613 (Div. 2)
    Codeforces Round #612 (Div. 2)
    CTF:第五题
    CTF:第四题
    CTF:第三题
    CTF,第二题
    CTF,第一题
    我也要做CTF了,哎,人老了,脑子需要动一动了,第一节,配置本地环境
    websocket JS使用方式
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9458129.html
Copyright © 2011-2022 走看看