zoukankan      html  css  js  c++  java
  • [spfa][最小生成树] Jzoj P4261 最小代价

    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

    题解

    • 一开始时,一直在想如果找到与哪个黑点相连
    • 可以考虑一下从建一个S源点,然后把黑点向S点连一条权值为0的边
    • 然后我们就可以求出从S点到所有点的最短距离
    • 问题就转换为了求白点到S的距离
    • 从S出发往回dfs,找到最短路径上的边
    • 一条边可能被多次经过,我们dfs可能会重复把边选出来,但题目要求一条边只加一次代价
    • 所以可以用Kruskal,把边连起来,避免重复边
    • 如果我们求的边权和ans==0,那么说明一条边也找不到,那么“impossible”

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std;
     8 const int inf=0x3f3f3f;
     9 struct edge {long long to,from,v; }e[300010*2],k[300010*2];
    10 long long dis[100010],ans,fa[100010],n,m,head[100010],cnt,tot;
    11 bool f[100010];
    12 queue<int>Q;
    13 void insert(int x,int y,int z) { e[++cnt].to=y; e[cnt].from=head[x]; e[cnt].v=z; head[x]=cnt; }
    14 void spfa()
    15 {
    16     memset(dis,inf,sizeof(dis));
    17     memset(f,false,sizeof(f));
    18     Q.push(0); dis[0]=0;
    19     while (!Q.empty())
    20     {
    21         int u=Q.front(); Q.pop();
    22         f[u]=false;
    23         for (int i=head[u];i;i=e[i].from)
    24             if (dis[u]+e[i].v<dis[e[i].to])
    25             {
    26                 dis[e[i].to]=dis[u]+e[i].v;
    27                 if (!f[e[i].to])
    28                 {
    29                     Q.push(e[i].to);
    30                     f[e[i].to]=true;
    31                 }
    32             }
    33     }
    34 }
    35 void dg(int x)
    36 {
    37     for (long long i=head[x];i;i=e[i].from)
    38         if (dis[x]+e[i].v==dis[e[i].to])
    39         {
    40             dg(e[i].to);
    41             k[++tot].from=x,k[tot].to=e[i].to,k[tot].v=e[i].v;
    42         }
    43 }
    44 long long getfather(int x)
    45 {
    46     if (fa[x]==x) return x;
    47     return fa[x]=getfather(fa[x]);
    48 }
    49 void kruskal()
    50 {
    51     for (long long i=1;i<=tot;i++)
    52     {
    53         long long x=getfather(k[i].from),y=getfather(k[i].to);
    54         if (x!=y)
    55         {
    56             ans+=k[i].v;
    57             fa[y]=x;
    58         }
    59     }
    60 }
    61 bool cmp(edge x,edge y) { return x.from<y.from; }
    62 int main()
    63 {
    64     scanf("%lld%lld",&n,&m);
    65     for (int i=1;i<=n;i++)
    66     {
    67         int x;
    68         scanf("%d",&x);
    69         if (x==1) insert(0,i,0);
    70     }
    71     for (int i=1;i<=m;i++)
    72     {
    73         int x,y,z;
    74         scanf("%d%d%d",&x,&y,&z);
    75         insert(x,y,z); insert(y,x,z);
    76     }
    77     spfa();
    78     dg(0);
    79     sort(k+1,k+tot+1,cmp);
    80     for (int i=1;i<=n;i++) fa[i]=i;
    81     kruskal();
    82     if (ans==0) printf("impossible"); else printf("%lld",ans);
    83 }
  • 相关阅读:
    MacBook下java环境的搭建
    Mac 终端下Homebrew的几个常用命令(新手笔记)
    新手学Appium_Python_Client
    【转】pycharm的一些快捷键
    解决YUM下Loaded plugins: fastestmirror Determining fastest mirrors 的问题
    chrome扩展第三方浏览器下载安装
    php异或加密解密算法的实现
    TortoiseGit客户端密钥配置
    CURL重试发送请求
    关于接收POST请求 $GLOBALS['HTTP_RAW_POST_DATA']
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9296326.html
Copyright © 2011-2022 走看看