CF400D Dima and Bacteria【并查集】

来源:互联网 发布:淘宝c店未来发展 编辑:程序博客网 时间:2024/06/03 21:56

题意:N个细菌,分成K种,每种C个,比如5个细菌,分为2种,C分别为2、3,那么1、2一类,3、4、5一类。有m边条u、v、c,u v之间花费为c。如果同一种细菌之间的任意两个花费不为0,输出No;否则Yes,输出不同类别细菌之间 的最短路。


思路:并查集,费用为0的边,合并。最后同一种类别的在一个集合就代表相互间花费为0。最短路,可以用Floyd。


#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<stdlib.h>#include<math.h>#include<vector>#include<list>#include<map>#include<set>#include<stack>#include<queue>#include<algorithm>#include<numeric>#include<functional>using namespace std;typedef long long ll;typedef pair<int,int> pii;const int maxn = 1e5+5;int dis[505][505];int zh[maxn],fen[505];int pre[maxn];void init(int n){for(int i = 0; i <= n; i++)pre[i] = i;}int fid(int x){if(pre[x] == x)return x;elsereturn pre[x] = fid(pre[x]);}void he(int x,int y){int nx = fid(x);int ny = fid(y);if(nx != ny)pre[nx] = ny;}int main(void){int n,m,k;while(scanf("%d%d%d",&n,&m,&k)!=EOF){init(n);int now = 1;fen[0] = 0;for(int i = 1; i <= k; i++){int t;scanf("%d",&t);fen[i] = t + fen[i-1];while(t--)zh[now++] = i;}memset(dis,0x3f,sizeof dis);while(m--){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(zh[a] != zh[b] && dis[zh[a]][zh[b]] > c)dis[zh[b]][zh[a]] = dis[zh[a]][zh[b]] = c;if(c == 0)he(a,b);}int ans = 1;for(int i = 1; i <= n; i++){int l = fen[i-1]+1;int r = fen[i];int flag = fid(l);for(int i = l; i <= r; i++){if(fid(i) != flag){ans = 0;break;}}if(!ans) break;}if(!ans)printf("No\n");else{for(int i = 1; i <= k; i++)dis[i][i] = 0;for(int kk = 1; kk <= k; kk++){for(int i = 1; i <= k; i++){for(int j = 1; j <= k; j++)dis[i][j] = min(dis[i][j],dis[i][kk]+dis[kk][j]);}}printf("Yes\n");for(int i = 1; i <= k; i++){for(int j = 1; j <= k; j++){if(dis[i][j] >= 0x3f3f3f3f)printf("-1%c",j==k?'\n':' ');elseprintf("%d%c",dis[i][j],j==k?'\n':' ');}}}}return 0;}