圣诞节将至。一年一度的难题又摆在wyx面前——如何给妹纸送礼物。
wyx的后宫有n人,这n人之间有着复杂的关系网,相互认识的人有m对。wyx想要量化后宫之间的亲密度,于是准备给每对认识关系估一个亲密度。亲密度是个正整数,值越大说明越亲密。当然有可能有些后宫之间不直接认识,为此wyx定义了一个值f(i,j),代表从第i个后宫开始不断经过认识的人到j,经过的亲密度最小的一对关系的最大值。不过也有可能有些后宫的朋友圈互相独立,怎么也没法通过认识的人互相到达,那么f(i,j)就为-1。
举个例子,wyx的后宫有4人,编号为1~4。后宫1和2之间的亲密度为3,后宫2和3之间的亲密度为4,后宫1和3之间的亲密度为2,后宫4由于不明原因被孤立了。那么f(1,2)=f(1,3)=3,f(2,3)=4,f(1,4)=f(2,4)=f(3,4)=-1。
wyx认为了解后宫之间的亲密程度对于他选择礼物有着很重大的意义,于是他找了几个路人,测出了所有后宫之间的f(i,j)值。不过wyx怀疑路人在坑爹,他想知道,是否能找到一组后宫之间的亲密度方案满足路人测出的f(i,j)值?由于他还要去把妹,这个问题就交给你了。
第一行一个正整数T,代表数据组数。
接下来T组数据,每组数据第一行两个正整数n、m,代表点数和边数。
接下来m行,每行两个正整数代表一条边。
接下来n行每行n个整数,代表所有的f(i,j)值。
对于每组数据,输出 "Yes" 或者 "No"。(详细参看样例输出)
1 //It is made by Awson on 2017.10.18
2 #include <set>
3 #include <map>
4 #include <cmath>
5 #include <ctime>
6 #include <queue>
7 #include <stack>
8 #include <vector>
9 #include <cstdio>
10 #include <string>
11 #include <cstring>
12 #include <cstdlib>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define link LINK
17 #define set SET
18 #define Max(a, b) ((a) > (b) ? (a) : (b))
19 #define Min(a, b) ((a) < (b) ? (a) : (b))
20 using namespace std;
21 void read(int &x) {
22 bool flag = 0;
23 x = 0;
24 char ch = getchar();
25 while ((ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘) ch = getchar();
26 if (ch == ‘-‘) flag = 1, ch = getchar();
27 while (ch >= ‘0‘ && ch <= ‘9‘) x = (x<<1)+(x<<3)+ch-48, ch = getchar();
28 x *= 1-2*flag;
29 }
30 const int N = 1000;
31 const int M = 300000;
32
33 int n, m;
34 struct ss {
35 int from, to, cost;
36 bool operator < (const ss &b) const{
37 return cost > b.cost;
38 }
39 }link[M+5];
40 int mp[N+5][N+5];
41 struct tt {
42 int to, cost, next;
43 }edge[(N<<1)+5];
44 int path[N+5], top;
45 int set[N+5];
46 int dist[N+5];
47
48 int find(int r) {
49 return set[r] ? set[r] = find(set[r]) : r;
50 }
51 void add(int u, int v, int c) {
52 edge[++top].to = v;
53 edge[top].cost = c;
54 edge[top].next = path[u];
55 path[u] = top;
56 }
57 void Kruskal() {
58 sort(link+1, link+1+m); int cnt = 0;
59 for (int i = 1; i <= m; i++) {
60 int p = find(link[i].from), q = find(link[i].to);
61 if (p != q) {
62 set[p] = q; cnt++;
63 add(link[i].from, link[i].to, link[i].cost);
64 add(link[i].to, link[i].from, link[i].cost);
65 if (cnt == n-1) break;
66 }
67 }
68 }
69 void dfs(int u, int fa, int mind) {
70 dist[u] = mind;
71 for (int i = path[u]; i; i = edge[i].next) if (edge[i].to != fa) dfs(edge[i].to, u, Min(mind, edge[i].cost));
72 }
73 void work() {
74 read(n), read(m); memset(path, 0, sizeof(path)); top = 0; memset(set, 0, sizeof(set));
75 for (int i = 1; i <= m; i++) read(link[i].from), read(link[i].to);
76 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) read(mp[i][j]);
77 for (int i = 1; i <= m; i++) link[i].cost = mp[link[i].from][link[i].to];
78 Kruskal();
79 for (int i = 1; i <= n; i++) {
80 memset(dist, -1, sizeof(dist));
81 dfs(i, 0, 2e9); dist[i] = 0;
82 for (int j = 1; j <= n; j++) if (dist[j] != mp[i][j]) {
83 printf("No\n"); return;
84 }
85 }
86 printf("Yes\n");
87 }
88 int main() {
89 int t;
90 read(t);
91 for (int i = 1; i <= t; i++) {
92 printf("Case #%d: ", i);
93 work();
94 }
95 return 0;
96 }