【CF】270D Design Tutorial: Inverse the Problem
题意异常的简单。就是给定一个邻接矩阵,让你判定是否为树。
算法1:O(n^3)。思路就是找到树边,原理是LCA。判断树边的数目是否为n-1。39-th个数据T了,自己测试2000跑到4s。
算法2:O(n^2)。思考由图如何得到树,显然MST是可行的。因此,题目变为直接找到MST。然后通过树边构建目标矩阵。判定矩阵是否相等。
1 /* 472D */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 using namespace std; 20 //#pragma comment(linker,"/STACK:102400000,1024000") 21 22 #define mpii map<int,int> 23 #define vi vector<int> 24 #define pii pair<int,int> 25 #define vpii vector<pair<int,int> > 26 #define rep(i, a, n) for (int i=a;i<n;++i) 27 #define per(i, a, n) for (int i=n-1;i>=a;--i) 28 #define pb push_back 29 #define mp make_pair 30 #define fir first 31 #define sec second 32 #define all(x) (x).begin(),(x).end() 33 #define SZ(x) ((int)(x).size()) 34 #define lson l, mid, rt<<1 35 #define rson mid+1, r, rt<<1|1 36 37 const int maxn = 2005; 38 const int INF = 0x3f3f3f3f; 39 int M[maxn][maxn]; 40 int T[maxn][maxn]; 41 int dist[maxn]; 42 int fa[maxn]; 43 bool visit[maxn]; 44 int n; 45 46 void kruskal() { 47 memset(visit, false, sizeof(visit)); 48 memset(dist, 0x3f, sizeof(dist)); 49 int v, mn; 50 int i, j, k; 51 52 dist[0] = 0; 53 for (i=0; i<n; ++i) { 54 mn = INF; 55 for (j=0; j<n; ++j) { 56 if (!visit[j] && dist[j]<mn) { 57 mn = dist[j]; 58 v = j; 59 } 60 } 61 62 assert(mn < INF); 63 64 for (j=0; j<n; ++j) { 65 if (visit[j]) { 66 T[j][v] = T[v][j] = T[j][fa[v]] + mn; 67 } 68 } 69 visit[v] = true; 70 71 for (j=0; j<n; ++j) { 72 if (M[v][j] < dist[j]) { 73 dist[j] = M[v][j]; 74 fa[j] = v; 75 } 76 } 77 } 78 } 79 80 int main() { 81 ios::sync_with_stdio(false); 82 #ifndef ONLINE_JUDGE 83 freopen("data.in", "r", stdin); 84 freopen("data.out", "w", stdout); 85 #endif 86 87 bool flag = true; 88 89 scanf("%d", &n); 90 91 rep(i, 0, n) 92 rep(j, 0, n) 93 scanf("%d", &M[i][j]); 94 95 rep(i, 0, n) { 96 if (M[i][i] != 0) { 97 flag = false; 98 goto _output; 99 } 100 rep(j, i+1, n) { 101 if (M[i][j]!=M[j][i] || M[i][j]==0) { 102 flag = false; 103 goto _output; 104 } 105 } 106 } 107 108 kruskal(); 109 110 rep(i, 0, n) { 111 rep(j, i+1, n) { 112 if (M[i][j] != T[i][j]) { 113 flag = false; 114 goto _output; 115 } 116 } 117 } 118 119 _output: 120 puts(flag ? "YES":"NO"); 121 122 #ifndef ONLINE_JUDGE 123 printf("time = %d.\n", (int)clock()); 124 #endif 125 126 return 0; 127 }