水题,因为我能想出来= =,一遍dfs(因为树一遍的性质, 连dp都不算)。。具体看代码吧。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 #define MAXV 100005 6 #define MAXE (1000002<<1) 7 8 int N; 9 int Vt[MAXE], Vefw[MAXE], Veh[MAXV],Veptr; 10 int Vsu[MAXV]; 11 long long SUMN; 12 char V_b8[MAXV]; 13 14 15 #define addedge(s, t) ({ 16 Vefw[Veptr] = Veh[s], Vt[Veptr] = t; 17 Veh[s] = ++Veptr; }) 18 19 /* 20 int leafrch(int s) 21 { 22 int leaf = s; 23 V_b8[s] = 1; 24 for(int e = Veh[s]; e; e = Vefw[e]) { 25 int t; 26 if (!V_b8[t = Vt[--e]]) { 27 int ret; 28 if (ret = leafrch(t)) { 29 leaf = ret; 30 break; 31 } 32 } 33 } 34 V_b8[s] = 0; 35 return leaf; 36 }*/ 37 38 long long diff_min; 39 #define abs(x) ((x)<0? -(x):(x)) 40 41 long long solve(int s) 42 { 43 long long sumn = Vsu[s]; 44 V_b8[s] = 1; 45 for(int e = Veh[s]; e; e = Vefw[e]) { 46 int t; 47 if (!V_b8[t = Vt[--e]]) 48 sumn += solve(t); 49 } 50 V_b8[s] = 0; 51 if (diff_min > abs(SUMN - (sumn << 1))) 52 diff_min = abs(SUMN - (sumn << 1)); 53 return sumn; 54 } 55 56 int main(void) 57 { 58 // freopen("poj3140.txt", "r", stdin); 59 int ncase, M; 60 61 for(ncase = 1;scanf("%d%d", &N, &M), N && M; ++ncase) { 62 SUMN = 0; 63 int i; 64 for(i=0; i<N; ++i) { 65 scanf("%d", &Vsu[i]); 66 SUMN += Vsu[i]; 67 } 68 diff_min = SUMN; 69 int fakeroot = 0; 70 for(i=0; i<M; ++i) { 71 int j, k; 72 scanf("%d%d", &j, &k); 73 --j, --k; 74 addedge(j, k), addedge(k, j); 75 if (fakeroot == k) fakeroot = j; 76 } 77 solve(fakeroot); // solve(leafrch(fakeroot)); 78 printf("Case %d: %lld ", ncase, diff_min); 79 memset(Veh, 0, sizeof(Veh)), Veptr = 0; 80 } 81 return 0; 82 }
有些代码被我注释掉了,注释前稍微快一点儿(我也不知道为嘛)。总时间复杂度O(N),其实已经临界了。
3140 | Accepted | 2820K | 282MS | G++ | 1481B | 2014-05-04 15:00:15 |
注释后:
3140 | Accepted | 2820K | 297MS | G++ | 1476B | 2014-05-04 15:05:46 |