題意:n<=2000的盒子,有一些裏面有球,再給你全部c[i][j](1<=i<=j<=n),即告訴你【i,j】裏面球的總數的奇偶性須要花費c[i][j],如今求知道全部的盒子的狀態須要最少花費爲多少。。c++
思路:PA系列的題目確實不錯。ide
思路比較有意思可是不難。spa
若是知道i,j之間任意兩點間的關係以及任意一個盒子的狀態,那麼很顯然i,j之間的全部盒子狀態均可以推出來。。那麼怎麼表示關係呢?code
很容易想到有關係就連一條邊,那麼就是求[1, n]之間的全部點有關係的最小花費嗎?那不就是最小生成樹嗎?blog
具體實現的話在i<->j+1連一條C[i][j]的邊,求1->n+1的最小生成樹。。get
code:it
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define Inf 0x3fffffff 4 #define repf(i, a, b) for (int i = (a); i <= (b); ++i) 5 const int maxn = 2003; 6 int c[maxn][maxn], d[maxn], vis[maxn]; 7 int n; 8 long long mst; 9 10 inline void read(int& ret){ 11 ret = 0; 12 bool ok = 0; 13 for( ; ;){ 14 int c = getchar(); 15 if (c >= '0' && c <= '9') ret = (ret << 3) + (ret << 1) + c - '0', ok = 1; 16 else if (ok) return; 17 } 18 } 19 20 void prim(){ 21 mst = 0; 22 memset(vis, 0, sizeof(vis)); 23 repf(i, 1, n+1) d[i] = c[1][i]; 24 vis[1] = 1; 25 repf(i, 1, n){ 26 int k = 0, mdis = Inf; 27 repf(j, 1, n+1) if (!vis[j] && d[j] < mdis) 28 k = j, mdis = d[j]; 29 vis[k] = 1; 30 mst += mdis; 31 repf(j, 1, n+1) if (!vis[j]) 32 d[j] = min(c[k][j], d[j]); 33 } 34 } 35 36 int main(){ 37 // freopen("a.in", "r", stdin); 38 while (scanf("%d", &n) != EOF){ 39 repf(i, 1, n) repf(j, i+1, n+1){ 40 read(c[i][j]); 41 c[j][i] = c[i][j]; 42 } 43 prim(); 44 cout << mst << endl; 45 } 46 }