zoukankan      html  css  js  c++  java
  • SDOJ 3742 黑白图

    【描述】

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

    【输入】

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

    【输出】

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

    【输入样例】

    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

    【输出样例】

    5

    【样例说明】

    选 2、4、6 三条边;

    【数据范围】

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

    ------------------------------------------------------------------------------------------------

    这道题有两个关键点,一是距离最近的黑点,一是价值最小。

    对于距离最近,我们可以建立一个超级汇点,汇点用零边连接每个黑点,然后从汇点开始跑最短路。

    因为汇点和黑点之间权值为0,所以汇点与白点之间跑出来的最短路是白点和黑点之间的最短路。

    对于第二点,价值最小,我们已经得到了最短路径图、确定了距离白点最近的黑点,所以可以跑一个最小生成树,在确保图连通的情况下得到最小价值。

    注:形成的最小生成树上的边不一定是白点到黑点最短距离的边,但可以肯定这个黑点是最优的,而且我们关注的是最小价值。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 #define N 200100
      8 #define INF 0x3f
      9 using namespace std;
     10 long long n,m,ans=0;
     11 bool vis[N];
     12 long long dis[N];
     13 long long fa[N];
     14 struct node
     15 {
     16     long long u,v,w,nxt;
     17 }e[N*2],d[N*2];
     18 long long first[N],cnt,tot;
     19 void ade(long long u,long long v,long long w)
     20 {
     21     e[++cnt].nxt=first[u]; first[u]=cnt;
     22     e[cnt].u=u; e[cnt].v=v; e[cnt].w=w;
     23 }
     24 queue<long long>q;
     25 void spfa(long long x)
     26 {
     27     memset(dis,0x3f,sizeof(dis));
     28     memset(vis,true,sizeof(vis));
     29     q.push(x);
     30     dis[x]=0;
     31     while(!q.empty())
     32     {
     33         long long u=q.front(); q.pop();
     34         vis[u]=true;
     35         for(long long i=first[u];i;i=e[i].nxt)
     36         {
     37             long long v=e[i].v;
     38             if(dis[v]>dis[u]+e[i].w)
     39             {
     40                 dis[v]=dis[u]+e[i].w;
     41                 if(vis[v]==true)
     42                 {
     43                     q.push(v);
     44                     vis[v]=false;
     45                 }
     46             }
     47         }
     48     }
     49 }
     50 inline bool cmp(node a,node b)
     51 {
     52     return a.w<b.w;
     53 }
     54 long long la(long long x)
     55 {
     56     if(fa[x]!=x)  fa[x]=la(fa[x]);
     57     return fa[x];
     58 }
     59 void kruskal()
     60 {
     61     sort(e+1,e+tot+1,cmp);
     62     for(long long i=1;i<=n;i++) fa[i]=i;
     63     long long cnnt=n;
     64     for(long long i=1;i<=tot;i++)
     65     {
     66         if(!cnnt) break;
     67         long long x=la(d[i].u);
     68         long long y=la(d[i].v);
     69         if(x==y) continue;
     70         fa[x]=y;
     71         ans+=d[i].w;
     72         --cnnt;
     73     }
     74 }
     75 int main()
     76 {
     77     scanf("%lld%lld",&n,&m);
     78     for(long long i=1,x;i<=n;i++)
     79     {
     80         scanf("%lld",&x);
     81         if(x==1) ade(n+1,i,0);//ade(i,n+1,0);//建立汇点 
     82     }
     83     for(long long i=1;i<=m;i++)
     84     {
     85         long long x,y,z;
     86         scanf("%lld%lld%lld",&x,&y,&z);
     87         ade(x,y,z);ade(y,x,z);
     88     }
     89     spfa(n+1);
     90 //    for(long long i=1;i<=n;i++) cout<<dis[i]<<" ";
     91 //    cout<<endl;
     92     bool pu=0;
     93     for(long long i=1;i<=n;i++)
     94     {
     95         if(dis[i]==INF) pu=1; 
     96         for(long long j=first[i];j;j=e[j].nxt)//!!!!!!!!建立新最短路图 
     97             if(dis[e[j].v]==dis[i]+e[j].w) 
     98                 d[++tot].u=i,d[tot].v=e[j].v,d[tot].w=e[j].w;
     99     }
    100 //    for(long long i=1;i<=tot;i++)
    101 //        cout<<d[i].u<<" "<<d[i].v<<" "<<d[i].w<<endl;
    102 //    cout<<endl;
    103     if(pu==1)
    104     {
    105         printf("impossible
    ");
    106         return 0;
    107     }
    108     kruskal();
    109     if(ans==0)
    110     {
    111         printf("impossible
    "); return 0;
    112     }
    113     printf("%lld
    ",ans);
    114     return 0;
    115 }
  • 相关阅读:
    web项目中添加logger日志
    oracle 创建表空间
    从request中读数据流
    通过request获取ID地址的方法
    创建表空间的sql语句
    plsql点击不再提示后需重新提示
    js文件报错Syntax error on token "Invalid Regular Expression Options", no accurate correction
    java知识
    DevC++出现[Error] ld returned 1 exit status,如何解决才好呢?
    1
  • 原文地址:https://www.cnblogs.com/kylara/p/9455483.html
Copyright © 2011-2022 走看看