zoukankan      html  css  js  c++  java
  • Codeforces 400D Dima and Bacteria(并查集最短路)

    题意:有n个k种细菌,每种细菌有ci个,各自标号为
    细菌之间(注意这里非种类之间)有m种转换关系,即u和v可相互转换,代价为x。
    若每种细菌内部可两两转换且代价为0,输出Yes,并且用矩阵输入各种类之间最小转换代价,不能转换的输出-1。
    否则输出No。
    思路:
    1、判断每种细菌内部可否两两转换且代价为0,可用并查集,对0边的两个细菌合并,最后判断每种细菌内部是否有共同祖先。
    2、各种类之间最小转换代价则用Floyd。
      1 #include <cstdio>
      2 #include <cstring>
      3 #define N 100005
      4 #define M 505
      5 #define INF 99999999
      6 
      7 int fa[N], rank[N], vis[N];
      8 int a[M][M], c[M], up[M], down[M];
      9 
     10 void Floyd(int n) {
     11     for (int k = 1; k <= n; k++) {
     12         for (int i = 1; i <= n; i++) {
     13             for (int j = 1; j <= n; j++) {
     14                 if((a[i][k] != INF) && (a[k][j] != INF)
     15                     &&(a[i][j] > a[i][k] + a[k][j] || a[i][j] == INF)) {
     16                         a[i][j] = a[i][k] + a[k][j];
     17                 }
     18             }
     19         }
     20     }
     21 }
     22 
     23 
     24 void Make_set(int n)
     25 {
     26     for(int i=1; i<=n; i++)
     27     {
     28         fa[i] = i;
     29         rank[i] = 0;
     30     }
     31 }
     32 int find(int x)//查找元素所在的父节点,回溯时压缩路径
     33 {
     34     if(x!=fa[x])
     35         fa[x]=find(fa[x]);
     36     return fa[x];
     37 }
     38 void Union(int x,int y)//按秩合并x,y所在的集合
     39 {
     40     x=find(x);
     41     y=find(y);
     42     if(x==y) return ;
     43     if(rank[x]>rank[y])
     44         fa[y]=x;
     45     else if(rank[x]<rank[y])
     46         fa[x]=y;
     47     else {
     48         rank[x]++;
     49         fa[y]=x;
     50     }
     51 }
     52 
     53 int main()
     54 {
     55     int n, m, k;
     56     scanf("%d%d%d",&n,&m,&k);
     57     Make_set(n);
     58     for(int i=1; i<=k; i++)
     59         scanf("%d",&c[i]);
     60     int tmp = 0;
     61     for(int i=1; i<=k; i++)
     62     {
     63         up[i] = tmp + 1;
     64         down[i] = tmp + c[i];
     65         tmp += c[i];
     66         for(int j=up[i]; j<=down[i]; j++) vis[j] = i;
     67     }
     68     for(int i=1; i<=k; i++)
     69         for(int j=i; j<=k; j++)
     70             a[i][j] = a[j][i] = INF;
     71 
     72     int x, y, d;
     73     for(int i=1; i<=m; i++)
     74     {
     75         scanf("%d%d%d",&x,&y,&d);
     76         int ta = vis[x], tb = vis[y];
     77         if(d==0//0边均
     78             Union(x, y);
     79         if(ta!=tb)
     80         {
     81             if(d<a[ta][tb])
     82                 a[ta][tb] = a[tb][ta] = d;
     83 
     84         }
     85     }
     86 
     87     int flag = 0;
     88     for(int i=1; i<=k; i++)
     89     {
     90         int flag1 = 0;
     91         int tmp = find(up[i]);
     92         for(int j=up[i]+1; j<=down[i]; j++)
     93         {
     94             if(find(j)!=tmp)
     95             {
     96                 flag1 = 1;
     97                 break;
     98             }
     99         }
    100         if(flag1 == 1)
    101         {
    102             flag=1;
    103             break;
    104         }
    105     }
    106     if(flag==0)
    107     {
    108         Floyd(k);
    109         printf("Yes ");
    110         for(int i=1; i<=k; i++)
    111         {
    112             for(int j=1; j<=k; j++)
    113             {
    114                 if(i==j) printf("");
    115                 else if(a[i][j]==INF) printf("-1 ");
    116                 else
    117                     printf("%d ",a[i][j]);
    118             }
    119             printf(" ");
    120         }
    121     }
    122     else
    123         printf("No ");
    124 
    125     return 0;
    126 }
    View Code

  • 相关阅读:
    安装和使用Glassfish
    3GP 的 DASH设计原则与标准
    hdu 2686 Matrix 最小费用最大流 或 多线程DP
    [Win32]客户端程序
    二叉查找树中节点的删除。
    Android:获取屏幕完整宽高,包含状态栏
    Django学习总结之五模型
    畸形的从业观
    调试版本和发行版本
    jsp中常见的错误处理(未完待续)
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3616592.html
Copyright © 2011-2022 走看看