暑假集训刷题记录

    向上跳,再向上跳,也许再努力一点我就能够着菊苣们的膝盖了。

                                          ——题记

 

7.23

    CodeForces 559C 组合数 + DP

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #include <map>

 5 #define MP make_pair

 6 #define F first

 7 #define S second

 8 using namespace std;

 9 

10 typedef long long LL;

11 typedef pair<LL, LL> Point;

12 

13 const int maxn = 22000 + 10;

14 const LL MOD = 1000000007LL;

15 

16 inline LL mul_mod(LL a, LL b)

17 {

18     a %= MOD; b %= MOD;

19     return (a * b) % MOD;

20 }

21 

22 inline LL sub_mod(LL a, LL b)

23 {

24     return (((a - b) % MOD) + MOD) % MOD;

25 }

26 

27 LL pow_mod(LL a, LL n)

28 {

29     LL ans = 1;

30     while(n)

31     {

32         if(n & 1) ans = mul_mod(ans, a);

33         a = mul_mod(a, a);

34         n >>= 1;

35     }

36     return ans;

37 }

38 

39 LL Inverse(LL a)

40 { return pow_mod(a, MOD - 2); }

41 

42 const int maxh = 200000 + 10;

43 

44 LL fac[maxh], invfac[maxh];

45 

46 void init()

47 {

48     fac[0] = fac[1] = 1;

49     for(int i = 2; i < maxh; i++) fac[i] = mul_mod(fac[i-1], i);

50     invfac[maxh-1] = Inverse(fac[maxh-1]);

51     for(int i = maxh-2; i >= 0; i--) invfac[i] = mul_mod(invfac[i+1], i+1);

52 }

53 

54 LL C(LL n, LL m)

55 {

56     if(m > n) { puts("shakalaka"); return 0; }

57     return mul_mod(mul_mod(fac[n], invfac[m]), invfac[n-m]);

58 }

59 

60 int h, w, n;

61 

62 Point a[maxn];

63 

64 LL methods(int i, int j)

65 {

66     LL x = a[j].first - a[i].first;

67     LL y = a[j].second - a[i].second;

68     return C(x + y, x);

69 }

70 

71 LL dp[maxn];

72 

73 int main()

74 {

75     //freopen("in.txt", "r", stdin);

76 

77     init();

78     scanf("%d%d%d", &h, &w, &n);

79     for(int i = 1; i <= n; i++)

80     {

81         LL x, y; scanf("%I64d%I64d", &x, &y);

82         a[i] = MP(x, y);

83     }

84     sort(a + 1, a + n + 1);

85     a[0] = MP(1, 1);

86     a[n+1] = MP(h, w);

87     dp[1] = methods(0, 1);

88 

89     for(int i = 2; i <= n + 1; i++)

90     {

91         dp[i] = methods(0, i);

92         for(int j = 1; j < i; j++) if(a[j].F <= a[i].F && a[j].S <= a[i].S)

93             dp[i] = sub_mod(dp[i], mul_mod(methods(j, i), dp[j]));

94     }

95 

96     printf("%I64d\n", dp[n + 1]);

97 

98     return 0;

99 }
代码君

    

    CodeForces 219D 树形DP

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #include <vector>

 5 using namespace std;

 6 

 7 const int maxn = 200000 + 10;

 8 int n;

 9 

10 vector<int> G[maxn];

11 vector<bool> f[maxn];

12 

13 int L[maxn];

14 int fa[maxn];

15 int up[maxn];

16 int rev[maxn];

17 int totup;

18 

19 void dfs(int u, int father, int d)

20 {

21     L[u] = d;

22     fa[u] = father;

23     for(int i = 0; i < G[u].size(); i++)

24     {

25         int v = G[u][i];

26         if(v == father) continue;

27         if(!f[u][i]) { totup++; up[v] = up[u] + 1; }

28         else up[v] = up[u];

29         dfs(v, u, d + 1);

30     }

31 }

32 

33 int main()

34 {

35     //freopen("in.txt", "r", stdin);

36     scanf("%d", &n);

37     for(int i = 0; i < n-1; i++)

38     {

39         int u, v; scanf("%d%d", &u, &v);

40         G[u].push_back(v); f[u].push_back(true);

41         G[v].push_back(u); f[v].push_back(false);

42     }

43 

44     dfs(1, 0, 0);

45 

46     for(int v = 1; v <= n; v++)

47         rev[v] = totup - up[v] + L[v] - up[v];

48 

49     int ans = n - 1;

50     for(int i = 1; i <= n; i++) ans = min(ans, rev[i]);

51 

52     printf("%d\n", ans);

53 

54     vector<int> hehe;

55     for(int i = 1; i <= n; i++) if(rev[i] == ans) hehe.push_back(i);

56 

57     printf("%d", hehe[0]);

58     for(int i = 1; i < hehe.size(); i++) printf(" %d", hehe[i]);

59     puts("");

60 

61     return 0;

62 }
代码君

 

7.24  补多校

 

7.25

    CodeForces 445B Tire树上的博弈

 1 #include <cstdio>

 2 #include <cstring>

 3 using namespace std;

 4 

 5 const int maxn = 100000 + 10;

 6 const int sigma_size = 26;

 7 

 8 int sz;

 9 int ch[maxn][sigma_size];

10 char str[maxn];

11 

12 void insert(char* s)

13 {

14     int u = 0;

15     for(int i = 0; s[i]; i++)

16     {

17         int c = s[i] - 'a';

18         if(!ch[u][c]) ch[u][c] = sz++;

19         u = ch[u][c];

20     }

21 }

22 

23 bool win[maxn], lose[maxn];

24 

25 void dfs(int u)

26 {

27     bool isleaf = true;

28     for(int c = 0; c < 26; c++) if(ch[u][c])

29     {

30         isleaf = false;

31         int v = ch[u][c];

32         dfs(v);

33         win[u] |= !win[v];

34         lose[u] |= !lose[v];

35     }

36     if(isleaf) win[u] = false, lose[u] = true;

37 }

38 

39 int main()

40 {

41     int n, k; scanf("%d%d", &n, &k);

42 

43     sz = 1;

44     for(int i = 0; i < n; i++)

45     {

46         scanf("%s", str);

47         insert(str);

48     }

49     dfs(0);

50 

51     if(!win[0]) puts("Second");

52     else if(lose[0]) puts("First");

53     else if(k & 1) puts("First");

54     else puts("Second");

55 

56     return 0;

57 }
代码君

     HDU 3996 网络流 最大权闭合图

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <algorithm>

  4 #include <vector>

  5 #include <queue>

  6 using namespace std;

  7 

  8 typedef long long LL;

  9 

 10 const int maxn = 3000;

 11 const LL INF = 10000000000;

 12 

 13 struct Edge

 14 {

 15     int from, to;

 16     LL cap, flow;

 17     Edge(int u, int v, LL c, LL f):from(u), to(v), cap(c), flow(f) {}

 18 };

 19 

 20 struct Dinic

 21 {

 22     int n, m, s, t;

 23     vector<Edge> edges;

 24     vector<int> G[maxn];

 25     int d[maxn], cur[maxn];

 26     bool vis[maxn];

 27 

 28     void init() { for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); }

 29 

 30     void AddEdge(int u, int v, LL c)

 31     {

 32         edges.push_back(Edge(u, v, c, 0));

 33         edges.push_back(Edge(v, u, 0, 0));

 34         m = edges.size();

 35         G[u].push_back(m - 2);

 36         G[v].push_back(m - 1);

 37     }

 38 

 39     bool BFS()

 40     {

 41         memset(vis, false, sizeof(vis));

 42         queue<int> Q;

 43         Q.push(s);

 44         vis[s] = true;

 45         d[s] = 0;

 46 

 47         while(!Q.empty())

 48         {

 49             int u = Q.front(); Q.pop();

 50             for(int i = 0; i < G[u].size(); i++)

 51             {

 52                 Edge& e = edges[G[u][i]];

 53                 int v = e.to;

 54                 if(!vis[v] && e.cap > e.flow)

 55                 {

 56                     vis[v] = true;

 57                     d[v] = d[u] + 1;

 58                     Q.push(v);

 59                 }

 60             }

 61         }

 62 

 63         return vis[t];

 64     }

 65 

 66     LL DFS(int u, LL a)

 67     {

 68         if(u == t || a == 0) return a;

 69         LL flow = 0, f;

 70         for(int& i = cur[u]; i < G[u].size(); i++)

 71         {

 72             Edge& e = edges[G[u][i]];

 73             int v = e.to;

 74             if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap-e.flow))) > 0)

 75             {

 76                 flow += f;

 77                 e.flow += f;

 78                 a -= f;

 79                 edges[G[u][i]^1].flow -= f;

 80                 if(a == 0) break;

 81             }

 82         }

 83         return flow;

 84     }

 85 

 86     LL MaxFlow()

 87     {

 88         LL flow = 0;

 89         while(BFS())

 90         {

 91             memset(cur, 0, sizeof(cur));

 92             flow += DFS(s, INF);

 93         }

 94         return flow;

 95     }

 96 }g;

 97 

 98 int main()

 99 {

100     int T; scanf("%d", &T);

101     for(int kase = 1; kase <= T; kase++)

102     {

103         int n; scanf("%d", &n);

104         g.n = n * 25 + 2;

105         g.init();

106         g.s = 0; g.t = g.n - 1;

107 

108         LL sum = 0;

109         for(int i = 0; i < n; i++)

110         {

111             int num; scanf("%d", &num);

112             for(int j = 1; j <= num; j++)

113             {

114                 int x = i * 25 + j;

115                 LL cost, value;

116                 int rela;

117                 scanf("%I64d%I64d%d", &cost, &value, &rela);

118 

119                 value -= cost;

120                 if(value > 0) { g.AddEdge(0, x, value); sum += value; }

121                 else g.AddEdge(x, g.t, -value);

122 

123                 while(rela--)

124                 {

125                     int a, b; scanf("%d%d", &a, &b); a--;

126                     int y = a * 25 + b;

127                     g.AddEdge(x, y, INF);

128                 }

129             }

130         }

131 

132         printf("Case #%d: %I64d\n", kase, sum - g.MaxFlow());

133     }

134 

135     return 0;

136 }
代码君

     HDU 3472 网络流 混合图的欧拉路径

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <vector>

  6 #include <queue>

  7 using namespace std;

  8 

  9 const int maxn = 30;

 10 const int INF = 1000000000;

 11 

 12 struct Edge

 13 {

 14     int from, to, cap, flow;

 15     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}

 16 };

 17 

 18 struct Dinic

 19 {

 20     int n, m, s, t;

 21     vector<Edge> edges;

 22     vector<int> G[maxn];

 23     int d[maxn], cur[maxn];

 24     bool vis[maxn];

 25 

 26     void init() { m = 0; for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); }

 27 

 28     void AddEdge(int u, int v, int c)

 29     {

 30         edges.push_back(Edge(u, v, c, 0));

 31         edges.push_back(Edge(v, u, 0, 0));

 32         m = edges.size();

 33         G[u].push_back(m - 2);

 34         G[v].push_back(m - 1);

 35     }

 36 

 37     bool BFS()

 38     {

 39         memset(vis, false, sizeof(vis));

 40         queue<int> Q;

 41         Q.push(s);

 42         d[s] = 0;

 43         vis[s] = true;

 44 

 45         while(!Q.empty())

 46         {

 47             int u = Q.front(); Q.pop();

 48             for(int i = 0; i < G[u].size(); i++)

 49             {

 50                 Edge& e = edges[G[u][i]];

 51                 int v = e.to;

 52                 if(!vis[v] && e.cap > e.flow)

 53                 {

 54                     vis[v] = true;

 55                     d[v] = d[u] + 1;

 56                     Q.push(v);

 57                 }

 58             }

 59         }

 60 

 61         return vis[t];

 62     }

 63 

 64     int DFS(int u, int a)

 65     {

 66         if(u == t || a == 0) return a;

 67         int flow = 0, f;

 68         for(int& i = cur[u]; i < G[u].size(); i++)

 69         {

 70             Edge& e = edges[G[u][i]];

 71             int v = e.to;

 72             if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap-e.flow))) > 0)

 73             {

 74                 flow += f;

 75                 e.flow += f;

 76                 a -= f;

 77                 edges[G[u][i]^1].flow -= f;

 78                 if(a == 0) break;

 79             }

 80         }

 81         return flow;

 82     }

 83 

 84     int MaxFlow()

 85     {

 86         int flow = 0;

 87         while(BFS())

 88         {

 89             memset(cur, 0, sizeof(cur));

 90             flow += DFS(s, INF);

 91         }

 92         return flow;

 93     }

 94 }g;

 95 

 96 const int maxm = 1000 + 10;

 97 int n;

 98 char word[30];

 99 

100 int deg[maxn];

101 

102 bool occur[maxn];

103 

104 int pa[maxn];

105 int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); }

106 void Union(int x, int y)

107 {

108     int px = findset(x), py = findset(y);

109     if(px != py) pa[px] = py;

110 }

111 

112 int u[maxm], v[maxm], directed[maxm];

113 int id[maxm];

114 

115 int main()

116 {

117     //freopen("in.txt", "r", stdin);

118 

119     int T; scanf("%d", &T);

120     for(int kase = 1; kase <= T; kase++)

121     {

122         printf("Case %d: ", kase);

123 

124         g.n = 28;

125         g.s = 26, g.t = 27;

126         g.init();

127         int n; scanf("%d", &n);

128 

129         for(int i = 0; i < 26; i++) pa[i] = i;

130         memset(id, 0, sizeof(id));

131         memset(occur, false, sizeof(occur));

132         memset(deg, 0, sizeof(deg));

133         memset(directed, 0, sizeof(directed));

134         for(int i = 0; i < n; i++)

135         {

136             scanf("%s%d", word, directed + i);

137             int l = strlen(word);

138             u[i] = word[0] - 'a';

139             v[i] = word[l - 1] - 'a';

140             occur[u[i]] = occur[v[i]] = true;

141             Union(u[i], v[i]);

142             deg[u[i]]++; deg[v[i]]--;

143             if(directed[i])

144             {

145                 id[i] = g.m;

146                 g.AddEdge(u[i], v[i], 1);

147             }

148         }

149 

150         //Judge the graph is connected

151         int root;

152         bool ok = true;

153         for(int i = 0; i < 26; i++) if(occur[i]) { root = findset(i); break; }

154         for(int i = 0; i < 26; i++) if(occur[i] && findset(i) != root)  { ok = false; break; }

155         int cnt = 0;

156         for(int i = 0; i < 26; i++) if(deg[i] & 1) cnt++;

157         if((cnt != 0) && cnt != 2) ok = false;

158         if(!ok) { puts("Poor boy!"); continue; }

159 

160         for(int i = 0; i < 26; i++) if(deg[i])

161         {

162             if(deg[i] > 0) g.AddEdge(g.s, i, deg[i] / 2);

163             else if(deg[i] < 0) g.AddEdge(i, g.t, -deg[i] / 2);

164         }

165         g.MaxFlow();

166 

167         for(int i = 0; i < n; i++) if(directed[i])

168         {

169             int x = id[i];

170             if(g.edges[x].flow == 1)

171                 { deg[u[i]] -= 2; deg[v[i]] += 2; }

172         }

173 

174         int a1 = 0, a2 = 0;

175         for(int i = 0; i < 26; i++) if(deg[i])

176         {

177             if(deg[i] == 1) a1++;

178             else if(deg[i] == -1) a2++;

179         }

180         if((a1 == 0 && a2 == 0) || (a1 == 1 || a2 == 1)) puts("Well done!");

181         else puts("Poor boy!");

182     }

183 

184     return 0;

185 }
代码君

    HDU 4183 网络流 每个点只能走一次的回路

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <vector>

  6 #include <queue>

  7 #include <cmath>

  8 using namespace std;

  9 

 10 const int maxn = 1000;

 11 const int INF = 1000000000;

 12 int n;

 13 

 14 struct Edge

 15 {

 16     int from, to, cap, flow;

 17     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}

 18 };

 19 

 20 struct Dinic

 21 {

 22     int n, m, s, t;

 23     vector<Edge> edges;

 24     vector<int> G[maxn];

 25     int d[maxn], cur[maxn];

 26     bool vis[maxn];

 27 

 28     void init() { m = 0; edges.clear(); for(int i = 0; i < n; i++) G[i].clear(); }

 29 

 30     void AddEdge(int u, int v, int c)

 31     {

 32         edges.push_back(Edge(u, v, c, 0));

 33         edges.push_back(Edge(v, u, 0, 0));

 34         m = edges.size();

 35         G[u].push_back(m - 2);

 36         G[v].push_back(m - 1);

 37     }

 38 

 39     bool BFS()

 40     {

 41         memset(vis, false, sizeof(vis));

 42         queue<int> Q;

 43         Q.push(s);

 44         vis[s] = true;

 45         d[s] = 0;

 46 

 47         while(!Q.empty())

 48         {

 49             int u = Q.front(); Q.pop();

 50             for(int i = 0; i < G[u].size(); i++)

 51             {

 52                 Edge& e = edges[G[u][i]];

 53                 int v = e.to;

 54                 if(!vis[v] && e.cap > e.flow)

 55                 {

 56                     vis[v] = true;

 57                     d[v] = d[u] + 1;

 58                     Q.push(v);

 59                 }

 60             }

 61         }

 62 

 63         return vis[t];

 64     }

 65 

 66     int DFS(int u, int a)

 67     {

 68         if(u == t || a == 0) return a;

 69         int flow = 0, f;

 70         for(int& i = cur[u]; i < G[u].size(); i++)

 71         {

 72             Edge& e = edges[G[u][i]];

 73             int v = e.to;

 74             if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap-e.flow))) > 0)

 75             {

 76                 flow += f;

 77                 e.flow += f;

 78                 a -= f;

 79                 edges[G[u][i]^1].flow -= f;

 80                 if(a == 0) break;

 81             }

 82         }

 83         return flow;

 84     }

 85 

 86     int MaxFlow()

 87     {

 88         int flow = 0;

 89         while(BFS())

 90         {

 91             memset(cur, 0, sizeof(cur));

 92             flow += DFS(s, INF);

 93         }

 94         return flow;

 95     }

 96 }g;

 97 

 98 const double eps = 1e-6;

 99 

100 int dcmp(double x)

101 {

102     if(fabs(x) < eps) return 0;

103     return x < 0 ? -1 : 1;

104 }

105 

106 struct Pad

107 {

108     double freq, x, y, r;

109     bool operator < (const Pad& rhs) const

110     { return freq > rhs.freq; }

111 }a[maxn];

112 

113 bool Intersect(int i, int j)

114 {

115     double d = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y-a[j].y)*(a[i].y-a[j].y));

116     return dcmp(a[i].r + a[j].r - d) > 0;

117 }

118 

119 int main()

120 {

121     //freopen("in.txt", "r", stdin);

122 

123     int T; scanf("%d", &T);

124     while(T--)

125     {

126         scanf("%d", &n);

127         g.n = n * 2 - 1;

128         g.init();

129         g.s = 0, g.t = n-1;

130         for(int i = 0; i < n; i++)

131         {

132             scanf("%lf%lf%lf%lf", &a[i].freq, &a[i].x, &a[i].y, &a[i].r);

133         }

134         sort(a, a + n);

135 

136         if(Intersect(0, n-1)) { puts("Game is VALID"); continue; }

137 

138         g.AddEdge(0, n, 2);

139         for(int i = 1; i < n - 1; i++) g.AddEdge(i, i + n, 1);

140         for(int i = 0; i < n; i++)

141             for(int j = i + 1; j < n; j++)

142                 if(dcmp(a[i].freq - a[j].freq) > 0 && Intersect(i, j))

143                     g.AddEdge(i + n, j, INF);

144 

145         if(g.MaxFlow() == 2) puts("Game is VALID");

146         else puts("Game is NOT VALID");

147     }

148 

149     return 0;

150 }
代码君

     CodeForces 461B 树形DP 跪舔题解

 1 #include <cstdio>

 2 #include <algorithm>

 3 #include <cstring>

 4 #include <vector>

 5 using namespace std;

 6 

 7 typedef long long LL;

 8 

 9 const int maxn = 100000 + 100;

10 const LL MOD = 1000000000 + 7;

11 int n;

12 int color[maxn];

13 vector<int> G[maxn];

14 

15 LL dp[maxn][2];

16 

17 void dfs(int u, int fa)

18 {

19     dp[u][color[u]] = 1;

20     for(int i = 0; i < G[u].size(); i++)

21     {

22         int v = G[u][i];

23         if(v == fa) continue;

24         dfs(v, u);

25         dp[u][1] = ((dp[u][1] * (dp[v][0] + dp[v][1])) % MOD + (dp[u][0]*dp[v][1])%MOD)%MOD;

26         dp[u][0] = (dp[u][0] * ((dp[v][0] + dp[v][1])%MOD))%MOD;

27     }

28 }

29 

30 int main()

31 {

32     scanf("%d", &n);

33     for(int u = 1; u < n; u++)

34     {

35         int v; scanf("%d", &v);

36         G[u].push_back(v);

37         G[v].push_back(u);

38     }

39     for(int i = 0; i < n; i++) scanf("%d", color + i);

40     dfs(0, -1);

41     printf("%I64d", dp[0][1]);

42 

43     return 0;

44 }
代码君

 

7.26

    CodeForces 455C 给出一个森林,可以合并两棵树。合并以后得到的新树的最小直径为

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #include <vector>

 5 using namespace std;

 6 

 7 const int maxn = 300000 + 10;

 8 int n, m, Q;

 9 

10 int diameter[maxn];

11 

12 bool vis[maxn];

13 int pa[maxn];

14 int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); }

15 void Union(int x, int y)

16 {

17     int px = findset(x), py = findset(y);

18     if(px != py) pa[px] = py;

19 }

20 

21 vector<int> G[maxn];

22 

23 int len, id;

24 

25 void dfs(int u, int fa, int d)

26 {

27     if(d > len) { len = d; id = u; }

28     for(int i = 0; i < G[u].size(); i++)

29     {

30         int v = G[u][i];

31         if(v != fa) dfs(v, u, d + 1);

32     }

33 }

34 

35 int longest(int v)

36 {

37     len = -1;

38     dfs(v, -1, 0);

39     len = -1;

40     dfs(id, -1, 0);

41     return len;

42 }

43 

44 int main()

45 {

46     scanf("%d%d%d", &n, &m, &Q);

47 

48     for(int i = 1; i <= n; i++)  pa[i] = i;

49     while(m--)

50     {

51         int u, v; scanf("%d%d", &u, &v);

52         G[u].push_back(v);

53         G[v].push_back(u);

54         Union(u, v);

55     }

56 

57     for(int i = 1; i <= n; i++)

58     {

59         int p = findset(i);

60         if(!vis[p])

61         {

62             vis[p] = true;

63             diameter[p] = longest(p);

64         }

65     }

66 

67     while(Q--)

68     {

69         int op, x, y;

70         scanf("%d%d", &op, &x);

71         if(op == 1)

72         {

73             printf("%d\n", diameter[findset(x)]);

74         }

75         else

76         {

77             scanf("%d", &y);

78             int px = findset(x), py = findset(y);

79             if(px == py) continue;

80             pa[px] = py;

81             int t = (diameter[px] + 1) / 2 + (diameter[py] + 1) / 2 + 1;

82             diameter[py] = max(diameter[px], max(diameter[py], t));

83         }

84     }

85 

86     return 0;

87 }
代码君

 

    CodeForces 274B 树形DP

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 #include <algorithm>

 6 using namespace std;

 7 

 8 typedef long long LL;

 9 

10 const int maxn = 100000 + 10;

11 

12 int n;

13 

14 vector<int> G[maxn];

15 LL val[maxn];

16 LL add[maxn], sub[maxn];

17 

18 void dfs(int u, int fa)

19 {

20     for(int i = 0; i < G[u].size(); i++)

21     {

22         int v = G[u][i];

23         if(v != fa)

24         {

25             dfs(v, u);

26             add[u] = max(add[u], add[v]);

27             sub[u] = max(sub[u], sub[v]);

28         }

29     }

30     val[u] += add[u] - sub[u];

31     if(val[u] > 0) sub[u] += val[u];

32     else if(val[u] < 0) add[u] += -val[u];

33 }

34 

35 int main()

36 {

37     scanf("%d", &n);

38     for(int i = 1; i < n; i++)

39     {

40         int u, v; scanf("%d%d", &u, &v);

41         G[u].push_back(v);

42         G[v].push_back(u);

43     }

44     for(int i = 1; i <= n; i++) scanf("%I64d", val + i);

45 

46     dfs(1, -1);

47     printf("%I64d\n", add[1] + sub[1]);

48 

49     return 0;

50 }
代码君

 

    CodeForces 337D

    题意:给出一棵n个节点的树,和m个特定的点。求这棵树中距所有这m个点的距离不超过d的点的个数。

    题解本来是给的DP的做法,评论下面有个给出了一种更好的方法:用类似求树的直径办法求出这m个点中相距最远的两个点a、b,然后算出所有点到a、b的距离。最终答案所统计的点就是距a、b不超过d的点的个数。

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <algorithm>

 5 #include <vector>

 6 using namespace std;

 7 

 8 const int maxn = 100000 + 10;

 9 

10 vector<int> G[maxn];

11 

12 int n, m, d;

13 

14 int p[maxn];

15 bool mark[maxn];

16 

17 int a, b;

18 

19 int len, id;

20 

21 void dfs1(int u, int fa, int d)

22 {

23     if(mark[u] && d > len) { len = d; id = u; }

24     for(int i = 0; i < G[u].size(); i++)

25     {

26         int v = G[u][i];

27         if(v == fa) continue;

28         dfs1(v, u, d + 1);

29     }

30 }

31 

32 int La[maxn], Lb[maxn];

33 

34 void dfs2(int u, int fa, int d, int* L)

35 {

36     L[u] = d;

37     for(int i = 0; i < G[u].size(); i++)

38     {

39         int v = G[u][i];

40         if(v == fa) continue;

41         dfs2(v, u, d + 1, L);

42     }

43 }

44 

45 int main()

46 {

47     //freopen("in.txt", "r", stdin);

48 

49     scanf("%d%d%d", &n, &m, &d);

50     for(int i = 0; i < m; i++)

51     {

52         scanf("%d", p + i);

53         mark[p[i]] = true;

54     }

55     for(int i = 1; i < n; i++)

56     {

57         int u, v; scanf("%d%d", &u, &v);

58         G[u].push_back(v); G[v].push_back(u);

59     }

60 

61     len = -1;

62     dfs1(p[0], 0, 0);

63     a = id;

64     len = -1;

65     dfs1(a, 0, 0);

66     b = id;

67 

68     dfs2(a, 0, 0, La);

69     dfs2(b, 0, 0, Lb);

70 

71     int ans = 0;

72     for(int i = 1; i <= n; i++) if(La[i] <= d && Lb[i] <= d) ans++;

73     printf("%d\n", ans);

74 

75     return 0;

76 }
代码君

 

    CodeForces 486D 树形DP 枚举集合中值最小的点(如果点一样的话就枚举取编号最小的那个)

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <algorithm>

 4 #include <cstring>

 5 #include <vector>

 6 using namespace std;

 7 

 8 typedef long long LL;

 9 

10 const int maxn = 2000 + 10;

11 const LL MOD = 1000000007;

12 

13 int d, n, root;

14 int a[maxn];

15 vector<int> G[maxn];

16 

17 LL dfs(int u, int fa)

18 {

19     LL ans = 1;

20     for(int i = 0; i < G[u].size(); i++)

21     {

22         int v = G[u][i];

23         if(v == fa) continue;

24         if(a[v] < a[root] || a[v] > a[root] + d) continue;

25         if(a[v] == a[root] && v < root) continue;

26         ans = (ans * (dfs(v, u) + 1)) % MOD;

27     }

28     return ans;

29 }

30 

31 int main()

32 {

33     scanf("%d%d", &d, &n);

34     for(int i = 1; i <= n; i++) scanf("%d", a + i);

35     for(int i = 1; i < n; i++)

36     {

37         int u, v; scanf("%d%d", &u, &v);

38         G[u].push_back(v); G[v].push_back(u);

39     }

40 

41     LL ans = 0;

42     for(int i = 1; i <= n; i++)

43     {

44         root = i;

45         ans = (ans + dfs(i, 0)) % MOD;

46     }

47 

48     printf("%I64d\n", ans);

49 

50     return 0;

51 }
代码君

 

    POJ 3744 概率DP + 矩阵快速幂优化

    先不考虑地雷,设f(x)表示走到位置x的概率。则有递推关系。所以在一段没有地雷的区间,可以快速计算走x步的概率。

 

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <algorithm>

 5 using namespace std;

 6 

 7 typedef double Mat[2][2];

 8 

 9 const int maxn = 12;

10 int n;

11 double p;

12 int pos[maxn];

13 

14 Mat A, E;

15 

16 void mul(Mat A, Mat B, Mat ans)

17 {

18     Mat C;

19     memset(C, 0, sizeof(C));

20     for(int i = 0; i < 2; i++)

21         for(int j = 0; j < 2; j++)

22             for(int k = 0; k < 2; k++)

23                 C[i][j] += A[i][k] * B[k][j];

24     memcpy(ans, C, sizeof(C));

25 }

26 

27 void pow(Mat A, int n, Mat ans)

28 {

29     Mat a, r;

30     memcpy(a, A, sizeof(a));

31     memset(r, 0, sizeof(r));

32     r[0][0] = r[1][1] = 1;

33     while(n)

34     {

35         if(n & 1) mul(r, a, r);

36         mul(a, a, a);

37         n >>= 1;

38     }

39 

40     memcpy(ans, r, sizeof(r));

41 }

42 

43 int main()

44 {

45     //freopen("in.txt", "r", stdin);

46 

47     while(scanf("%d", &n) == 1 && n)

48     {

49         scanf("%lf", &p);

50         for(int i = 0; i < n; i++) scanf("%d", pos + i);

51         sort(pos, pos + n);

52         n = unique(pos, pos + n) - pos;

53 

54         if(pos[0] == 1) { puts("0.0000000"); continue; }

55         bool flag = false;

56         for(int i = 0; i + 1 < n; i++) if(pos[i] + 1 == pos[i+1]) { flag = true; break; }

57         if(flag) { puts("0.0000000"); continue; }

58 

59         Mat x, t;

60         x[0][0] = 0; x[0][1] = 1; x[1][0] = 1- p; x[1][1] = p;

61         pow(x, pos[0] - 2, t);

62         double ans = t[1][1];

63 

64         for(int i = 1; i < n; i++)

65         {

66             ans *= 1.0 - p;

67             pow(x, pos[i]-pos[i-1]-2, t);

68             ans *= t[1][1];

69         }

70 

71         printf("%.7f\n", ans * (1.0 - p));

72     }

73 

74     return 0;

75 }
代码君

 

你可能感兴趣的:(记录)