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 }
  • 相关阅读:
    Educational Codeforces Round 85 D. Minimum Euler Cycle(模拟/数学/图)
    Educational Codeforces Round 85 C. Circle of Monsters(贪心)
    NOIP 2017 提高组 DAY1 T1小凯的疑惑(二元一次不定方程)
    Educational Codeforces Round 85 B. Middle Class(排序/贪心/水题)
    Educational Codeforces Round 85 A. Level Statistics(水题)
    IOS中的三大事件
    用Quartz 2D画小黄人
    strong、weak、copy、assign 在命名属性时候怎么用
    用代码生成UINavigationController 与UITabBarController相结合的简单QQ框架(部分)
    Attempting to badge the application icon but haven't received permission from the user to badge the application错误解决办法
  • 原文地址:https://www.cnblogs.com/kylara/p/9455483.html
Copyright © 2011-2022 走看看