zoukankan      html  css  js  c++  java
  • codeforces 400D Dima and Bacteria 并查集+floyd

    题目链接:http://codeforces.com/problemset/problem/400/D

    题目大意:

      给定n个集合,m步操作,k个种类的细菌,

      第二行给出k个数表示连续的xi个数属于i集合。

      当某个种类之间两两交换的值都为0可行解,则输出所有种类之间交换的最小值;否则输出No

    解题思路:当两点之间的距离为0时并查集到一个集合中,只需保证最终同一种类的细菌都在一个并查集中则是符合条件的可行解,再用FLOYD找最短路即可

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define FFF 100005
      8 int set[FFF];
      9 int a[FFF];
     10 int sw[505][505];
     11 int cnt[505];
     12 int vis[FFF];
     13 int n,k,m;
     14 
     15 int find(int x)
     16 {
     17     if(x==set[x])
     18         return x;
     19     else return set[x]=find(set[x]);
     20 }
     21 
     22 void uion(int x,int y)
     23 {
     24     int l1=find(x);
     25     int l2=find(y);
     26     if(l1==l2)
     27         return;
     28     else
     29         set[l2]=l1;
     30     return;
     31 }
     32 
     33 bool judge()
     34 {
     35     for(int l=1;l<=k;l++)
     36     {
     37         int tmp=-1;
     38         for(int i=cnt[l-1]+1;i<=cnt[l];i++)
     39         {
     40             if(tmp==-1)
     41                 tmp=find(i);
     42             else
     43             {
     44                 if(tmp!=find(i))
     45                     return false;
     46             }
     47         }
     48     }
     49     return true;
     50 }
     51 
     52 void solve()
     53 {
     54     for(int l=1;l<=k;l++)
     55     {
     56         for(int i=1;i<=k;i++)
     57         {
     58             if(i!=l)
     59             {
     60                 for(int j=1;j<=k;j++)
     61                 {
     62                     if(j!=l&&j!=i)
     63                     {
     64                         if((sw[i][l]+sw[l][j]<sw[i][j]||sw[i][j]<0)&&sw[i][l]>=0&&sw[l][j]>=0)
     65                             sw[i][j]=sw[i][l]+sw[l][j];
     66                     }
     67                 }
     68             }
     69         }
     70     }
     71     return;
     72 }
     73 
     74 void print()
     75 {
     76     for(int i=1;i<=k;i++)
     77     {
     78         sw[i][i]=0;
     79         for(int j=1;j<=k;j++)
     80         {
     81             if(j==1)
     82                 printf("%d",sw[i][j]);
     83             else
     84                 printf(" %d",sw[i][j]);
     85         }
     86         cout<<endl;
     87     }
     88     return;
     89 }
     90 
     91 int main()
     92 {
     93     int i,j,now;
     94     scanf("%d%d%d",&n,&m,&k);
     95     //n为点的总个数,m为边数,k为种类数
     96     for(i=1,now=1;i<=k;i++)
     97     {
     98         int x;
     99         scanf("%d",&x);
    100         // 第i种细菌有x个
    101         for( j=0;j<x;j++)
    102         {
    103             a[j+now]=i;
    104             set[j+now]=j+now;
    105         }
    106         now+=x;
    107         cnt[i]=now-1;
    108     }
    109     memset(sw,-1,sizeof(sw));
    110     // 两两种类之间的代价初始化成-1
    111     while(m--)
    112     {
    113         int x,y,z;
    114         scanf("%d%d%d",&x,&y,&z);
    115         if(a[x]==a[y])
    116         //属于同一种类
    117         {
    118             if(z==0)
    119                 uion(x,y);
    120             // 添入并查集
    121         }
    122         else
    123         //不同种类的细菌
    124         {
    125             if(z==0)
    126                 uion(x,y);
    127             if(sw[a[x]][a[y]]==-1)
    128             // 该两类之间还没有交换代价
    129                 sw[a[x]][a[y]]=sw[a[y]][a[x]]=z;
    130             else if(z<sw[a[x]][a[y]])
    131             // 新的代价较小的情况
    132                 sw[a[x]][a[y]]=sw[a[y]][a[x]]=z;
    133         }
    134     }
    135     if(!judge())
    136     // 判断同种类的细菌之间是否为0
    137         printf("No
    ");
    138     else
    139     {
    140         printf("Yes
    ");
    141         solve();
    142         // floyd找最短路
    143         print();
    144     }
    145     return 0;
    146 }
    147 
    148 /*
    149 FLOYD
    150 题目大意:给定n个集合,m步操作,k个种类的细菌,
    151             第二行给出k个数表示连续的xi个数属于i集合。
    152             当某个种类之间两两交换的值都为0可行解
    153 解题思路:当两点之间的距离为0时并查集到一个集合中,
    154             最终保证同种细菌都在一个并查集中
    155             再用FLOYD找最短路*/
    View Code
  • 相关阅读:
    个推微服务网关架构实践
    NB-IoT 的“前世今生”
    个推基于Consul的配置管理
    个推Node.js 微服务实践:基于容器的一站式命令行工具链
    个推用户画像的实践与应用
    TensorFlow分布式实践
    个数是如何用大数据做行为预测的?
    QCon技术干货:个推基于Docker和Kubernetes的微服务实践
    基于CMS的组件复用实践
    数据可视化:浅谈热力图如何在前端实现
  • 原文地址:https://www.cnblogs.com/wuwing/p/3644961.html
Copyright © 2011-2022 走看看