第一个做的第五道题,其实我觉得我写的还不错的。。。
题目,思路,数据,代码见下:
我的思路
按照拓扑排序DP
用S[i]表示 i 的最大价值,那么有
中间做了一点优化,貌似是拖慢了时间。但其实有多种优化思路,主要根据矩阵是稀疏还是稠密,我做的优化比较折中。比如缓存了一些路径上的距离等,但结果貌似是省了内存,但是TLE。。。
Sample
样例输入
1
12
0 0 10 30
1 10 10 11
1 100 10 10
2 20 10 7
2 5 10 9
4 8 5 1
5 5 5 4
7 5 1 1
3 1 200 1
6 3 22 22
9 10 99 0
11 10 6 8
样例输出
224
样例输入
10
10
0 0 981021 2878
1 2982 103544 16423
2 9309 1146606 60
1 9632 339699 4022
1 4859 1050430 27644
4 7152 1016794 8381
2 691 202924 1579
5 682 312623 1947
1 5622 434383 1966
1 1036 337962 4867
10
0 0 613160 4178
1 6039 530965 36077
1 2641 588435 10697
2 8015 1773940 21360
2 9456 1536141 20760
3 1540 1069223 6060
3 4132 1802960 9712
4 1295 338084 630
4 5977 858393 3942
5 1981 1569807 8875
10
0 0 3297948 29281
1 2838 4499071 56444
2 1723 5082712 58167
3 6932 1899951 86996
4 6111 4673596 39622
5 4854 1283153 52866
6 1600 3076850 58518
7 2887 3936856 44586
8 9662 1653482 1115
9 6359 1438146 7533
10
0 0 3827584 9067
1 1114 1938309 90351
2 1913 3135879 31961
3 210 3118784 55465
4 6982 1115456 4482
5 4326 2504229 8147
6 3567 1296569 21072
6 857 3723988 867
7 2726 1349738 682
6 2569 1465079 9994
10
0 0 4152770 20839
1 3728 1993622 104795
2 3358 1563274 31216
3 6794 2231093 43445
4 2197 2316621 7602
5 1174 2985157 7136
6 8333 103275 6346
6 5129 3083322 3511
7 469 2368248 9692
7 5732 3765843 8563
10
0 0 3091416 127451
1 2323 3358598 10828
2 8139 3723827 15116
3 9725 2486973 25964
4 1954 2821451 18368
5 8257 3938729 32443
6 2554 4006939 13576
6 5881 511102 9605
7 7999 1954660 1148
7 3260 1916815 8710
10
0 0 366406 31967
1 7426 2566312 2237
1 654 2294113 5913
2 8186 893528 10662
2 6453 1512505 13321
4 6429 616635 6615
6 5842 2578315 14449
5 3568 2988564 9781
6 1704 1044306 9036
7 4747 155934 4217
10
0 0 2481887 67676
1 2514 2068792 41590
2 5134 2460668 181
1 608 1693903 5729
2 2202 2804903 37359
5 611 1673964 6522
6 429 1245126 10648
6 7898 358662 6483
7 4194 1315545 8960
6 1193 224838 7332
10
0 0 3403835 116677
1 77 2005502 44152
2 2913 3325129 47250
2 8094 2319341 37
3 3750 458636 52717
5 8465 1635392 21518
6 9440 1757959 2079
6 8555 2306608 4397
6 5530 2658501 440
7 1594 1833614 690
10
0 0 1477756 44072
1 8380 3425538 18191
2 7951 978970 6357
1 2602 184752 6671
3 725 2947560 1525
5 1314 3589295 39573
6 1755 1675874 6532
6 8848 2470638 3789
7 1620 2129738 9070
7 9509 2363613 6569
样例输出
970205
613151
0
4682720
3959657
2626087
19106
0
1522734
5999689
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <iterator>
#include <algorithm>
#include <stack>
using namespace std;
inline int read_int() { int a; scanf("%d", &a); return a; }
inline void outd(int x) { printf("%d", x); }
inline void outdn(int x) { printf("%d\n", x); }
inline void outn() { printf("\n"); }
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int T = read_int();
while (T--)
{
int n = read_int();
// ref[] : the number of children, used for topology sorting.
// S[] : the max value of the cities.
vector<int> uu(n + 1), ss(n + 1), vv(n + 1), ff(n + 1), ref(n + 1);
vector<long long> S(n + 1);
vector<unordered_map<int, int> > distance(n + 1);
vector<unordered_set<int> > reachable(n + 1);
int u, s, v, f;
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d %d", &u, &s, &v, &f);
uu[i] = u;
ss[i] = s;
vv[i] = v;
ff[i] = f;
if (u != 0)
{
distance[u][i] = s; // dis[0] has one element, dis[0][1] = 0.
reachable[u].insert(i);
ref[u]++;
}
}
ref[0] = 0;
// preserve the succeeding nodes.
vector<unordered_set<int> > next = reachable;
// compute reachable[][]
for (int i = 0; i < n - 2; i++)
{
for (int j = 1; j <= n; j++)
{
unordered_set<int>& j_to = reachable[j];
const int unreach_size = n - 1 - j_to.size();
int new_reach_size = 0;
for (int k = 1; k <= n; k++)
{
if (j == k || unreach_size == new_reach_size || j_to.count(k)) continue;
for (int t = 1; t <= n; t++)
if (j_to.count(t) && reachable[t].count(k))
{
j_to.insert(k);
new_reach_size++;
break;
}
}
}
}
// DP: S[i] = max { S[j] + v[i] - (f[i] - dis[i][j])^2 }, where i to j.
// topology sorting to determine the next to be computed.
stack<int> stk;
for (int i = 1; i <= n; i++)
if (ref[i] == 0)
stk.push(i);
while (!stk.empty())
{
const int i = stk.top(); stk.pop();
int ui = uu[i];
if (--ref[ui] == 0) // note that ref[0] == 0
stk.push(ui);
// begin DP
const unordered_set<int>& reach_set = reachable[i];
for (unordered_set<int>::const_iterator it = reach_set.cbegin(); it != reach_set.cend(); ++it)
{
const int j = *it;
int dij = 0, cur_pos = j;
// get dij
const unordered_set<int>& i_next = next[i];
for (unordered_set<int>::const_iterator i_next_it = i_next.cbegin(); i_next_it != i_next.cend(); ++i_next_it)
{
const int inext = *i_next_it;
if (inext == j)
{
distance[i][j] = dij = ss[inext];
break;
}
if (reachable[inext].count(j))
{
distance[i][j] = dij = distance[inext][j] + ss[inext];
break;
}
}
const long long delta = ff[i] - dij;
S[i] = max(S[i], S[j] + vv[i] - delta * delta);
}
}
long long result = 0;
for (int i = 1; i <= n; i++)
result += S[i];
printf("%llu\n", (result % (unsigned long long)1e18));
}
system("pause");
return 0;
}