Codeforces 400D Dima and Bacteria(并查集最短路)
题意:有n个k种细菌,每种细菌有ci个,各自标号为
细菌之间(注意这里非种类之间)有m种转换关系,即u和v可相互转换,代价为x。
若每种细菌内部可两两转换且代价为0,输出Yes,并且用矩阵输入各种类之间最小转换代价,不能转换的输出-1。
否则输出No。
思路:
1、判断每种细菌内部可否两两转换且代价为0,可用并查集,对0边的两个细菌合并,最后判断每种细菌内部是否有共同祖先。
2、各种类之间最小转换代价则用Floyd。
细菌之间(注意这里非种类之间)有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\n");
110 for(int i=1; i<=k; i++)
111 {
112 for(int j=1; j<=k; j++)
113 {
114 if(i==j) printf("0 ");
115 else if(a[i][j]==INF) printf("-1 ");
116 else
117 printf("%d ",a[i][j]);
118 }
119 printf("\n");
120 }
121 }
122 else
123 printf("No\n");
124
125 return 0;
126 }
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\n");
110 for(int i=1; i<=k; i++)
111 {
112 for(int j=1; j<=k; j++)
113 {
114 if(i==j) printf("0 ");
115 else if(a[i][j]==INF) printf("-1 ");
116 else
117 printf("%d ",a[i][j]);
118 }
119 printf("\n");
120 }
121 }
122 else
123 printf("No\n");
124
125 return 0;
126 }