牛客国庆集训派对Day6 Solution

A    Birthday

思路:设置一个源点,一个汇点,每次对$源点对a_i, b_i , a_i 对 b_i 连一条流为1,费用为0的边$

每个点都再连一条 1, 3, 5, 7, ....的边到汇点之间,因为每多加一个流的费用,然后就是最小费用最大流

  1 #include<bits/stdc++.h>
  2  
  3 using namespace std;
  4  
  5 const int INF = 0x3f3f3f3f;
  6  
  7 const int maxn = 1010;
  8 const int maxm = 10010;
  9  
 10 struct Edge{
 11     int to, nxt, cap, flow, cost;
 12 }edge[maxm];
 13  
 14 int head[maxn], tot;
 15 int pre[maxn], dis[maxn];
 16 bool vis[maxn];
 17 int N;
 18  
 19 void Init(int n)
 20 {
 21     N = n;
 22     tot = 0;
 23     memset(head, -1, sizeof head);
 24 }
 25  
 26 void addedge(int u, int v, int cap, int cost)
 27 {
 28     edge[tot].to = v;
 29     edge[tot].cap = cap;
 30     edge[tot].cost = cost;
 31     edge[tot].flow = 0;
 32     edge[tot].nxt = head[u];
 33     head[u] = tot++;
 34  
 35     edge[tot].to = u;
 36     edge[tot].cap = 0;
 37     edge[tot].cost = -cost;
 38     edge[tot].flow = 0;
 39     edge[tot].nxt = head[v];
 40     head[v] = tot++;
 41 }
 42  
 43 bool SPFA(int s, int t)
 44 {
 45     queue<int>q;
 46     for(int i = 0; i < N; ++i)
 47     {
 48         dis[i] = INF;
 49         vis[i] = false;
 50         pre[i] = -1;
 51     }
 52     dis[s] = 0;
 53     vis[s] = true;
 54     q.push(s);
 55     while(!q.empty())
 56     {
 57         int u = q.front();
 58         q.pop();
 59         vis[u] = false;
 60         for(int i = head[u]; ~i; i = edge[i].nxt)
 61         {
 62             int v = edge[i].to;
 63             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)
 64             {
 65                 dis[v] = dis[u] + edge[i].cost;
 66                 pre[v] = i;
 67                 if(!vis[v])
 68                 {
 69                     vis[v] = true;
 70                     q.push(v);
 71                 }
 72             }
 73         }
 74     }
 75     if(pre[t] == -1) return false;
 76     else return true;
 77 }
 78  
 79 int solve(int s,int t)
 80 {
 81     int flow = 0 ;
 82     int cost = 0;
 83     while(SPFA(s, t))
 84     {
 85         int Min = INF;
 86         for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to])
 87         {
 88             Min = min(Min, edge[i].cap - edge[i].flow);
 89         }
 90         for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to])
 91         {
 92             edge[i].flow += Min;
 93             edge[i ^ 1].flow -= Min;
 94             cost += edge[i].cost * Min;
 95         }
 96         flow += Min;
 97     }
 98     return cost;
 99 }
100  
101 int n, m;
102  
103 int main()
104 {
105     while(~scanf("%d %d", &n, &m))
106     {
107         Init(n + m + 2);
108         int s = 0, t = n + m + 1;
109         for(int i = 1; i <= n; ++i)
110         {
111             int u, v;
112             scanf("%d %d", &u, &v);
113             addedge(0, i, 1, 0);
114             addedge(i, u + n, 1, 0);
115             addedge(i, v + n, 1, 0);
116         }
117         for(int i = n + 1; i <= n + m; ++i)
118         {
119             for(int j = 1; j < 100; j += 2)
120             {
121                 addedge(i, t, 1, j);
122             }
123         }
124         int cost = solve(0, n + m + 1);
125         printf("%d
", cost);
126     }
127     return 0;
128 }
View Code

B    Board

思路一:考虑 $a[x], b[x]$ 分别表示第x行加了多少, 第x列加了多少 那么 $arr[x][y]$ 就可以表示成 $a[x] + b[y]$ 那么 就可以通过找一个点来解,比如说找一个点$x_1, y_1$ 那么 $a[x] + b[y] = a[x] + b[y_1] + a[x_1] + b[y] - a[x_1] - b[x_1] = arr[x][y_1] + arr[x_1][y] - arr[x_1][y_1]$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define N 1010
 5  
 6 int n;
 7 int arr[N][N];
 8  
 9 int Move[4][2] =
10 {
11     -1, -1,
12      1,  1,
13     -1,  1,
14      1, -1,
15 };
16  
17 bool ok(int x, int y)
18 {
19     if (x < 1 || x > n || y < 1 || y > n) return false;
20     return true;
21 }
22  
23 int main()
24 {
25     while (scanf("%d", &n) != EOF)
26     {
27         int x, y;
28         for (int i = 1; i <= n; ++i)
29             for (int j = 1; j <= n; ++j)
30             {
31                 scanf("%d", &arr[i][j]);
32                 if (arr[i][j] == -1)
33                     x = i, y = j;
34             }
35         if (n == 1)
36             printf("%d
", arr[1][1] == -1 ? 0 : arr[1][1]);
37         else
38         {
39             for (int i = 0; i < 4; ++i)
40             {
41                 int nx = x + Move[i][0];
42                 int ny = y + Move[i][1];
43                 if (ok(nx, ny))
44                 {
45                     printf("%d
", arr[x][ny] + arr[nx][y] - arr[nx][ny]);
46                     break;
47                 }
48             }
49         }
50     }
51     return 0;
52 }
View Code

思路二:考虑分成n块,包含n行n列,那么每次对每一列加上一个数或者对每一行加上一个数,相当于对n块都加上了,也就是说,这n个块最后相加的数是相同的,然后就可以求解

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 #define N 1010
 6  
 7 int n;
 8 int arr[N][N];
 9 int sum[N];
10 int x, y;
11  
12 int main()
13 {
14     while(~scanf("%d", &n))
15     {
16         memset(sum, 0, sizeof sum);
17         for(int i = 1; i <= n; ++i)
18         {
19             for(int j = 1; j <= n; ++j)
20             {
21                 scanf("%d", &arr[i][j]);
22                 if(arr[i][j] != -1) sum[(i + j) % n] += arr[i][j];
23                 else x = i, y = j;
24             }
25         }
26         int tmp = (x + y) % n;
27         int ans = 0;
28         if(tmp != 0)
29         {
30             ans = sum[0] - sum[tmp];
31         }
32         else
33         {
34             ans = sum[1] - sum[tmp];
35         }
36         printf("%d
", ans);
37     }
38     return 0;
39 }
View Code

C    Circle

水。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n;
 5 
 6 int main()
 7 {
 8     while (scanf("%d", &n) != EOF)
 9         printf("%d
", n);
10     return 0;
11 }
View Code

D    土龙弟弟

留坑。

E    Growth

思路:考虑将$x, y 分别离散  dp[x][y]$ 表示 $a_i, b_i 到达 x, y $的状态 的时候可以拿到多少奖励了

$value[x][y] 表示的是 到达x并且到达y 的奖励一共有多少$

$dp[i][j] = max(dp[i][j - 1] + value[i][j - 1] *(yy[j] -  yy[j - 1]), dp[i - 1][j] + value[i - 1][j] * (xx[i] - xx[i - 1]));$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define N 1010
 5 #define ll long long
 6  
 7 int n, mx, my;
 8 ll m;
 9 int xx[N], yy[N], zz[N];
10 ll dp[N][N], value[N][N];
11  
12 struct node
13 {
14     int x, y, z;
15     void scan(int i)
16     {
17         scanf("%d%d%d", &x, &y, &z);
18         xx[i] = x; yy[i] = y;
19     }
20 }arr[N];
21  
22 void Init()
23 {
24     sort(xx + 1, xx + 1 + n);
25     sort(yy + 1, yy + 1 + n);
26     mx = unique(xx + 1, xx + 1 + n) - xx - 1;
27     my = unique(yy + 1, yy + 1 + n) - yy - 1;
28     memset(dp, 0, sizeof dp);
29     memset(value, 0, sizeof value);
30     for (int i = 1; i <= n; ++i)
31     {
32         arr[i].x = lower_bound(xx + 1, xx + 1 + mx, arr[i].x) - xx;
33         arr[i].y = lower_bound(yy + 1, yy + 1 + my, arr[i].y) - yy;
34         value[arr[i].x][arr[i].y] += arr[i].z;
35     }
36 }
37  
38 int main()
39 {
40     while (scanf("%d%lld", &n, &m) != EOF)
41     {
42         for (int i = 1; i <= n; ++i) arr[i].scan(i); Init();
43         for (int i = 1; i <= mx; ++i)
44         {
45             for (int j = 1; j <= my; ++j)
46             {
47                 value[i][j] += value[i - 1][j] + value[i][j - 1] - value[i - 1][j - 1];
48             }
49         }
50         for (int i = 1; i <= mx; ++i)
51         {
52             for (int j = 1; j <= my; ++j)
53             {
54                 dp[i][j] = max(dp[i][j], dp[i - 1][j] + value[i - 1][j] * (xx[i] - xx[i - 1]));
55                 dp[i][j] = max(dp[i][j], dp[i][j - 1] + value[i][j - 1] * (yy[j] - yy[j - 1]));
56             }
57         }
58         ll ans = 0;
59         for (int i = 1; i <= mx; ++i)
60         {
61             for (int j = 1; j <= my; ++j)
62             {
63                 if(xx[i] + yy[j] <= m) ans = max(ans, dp[i][j] + value[i][j] * (m - xx[i] - yy[j] + 1));
64             }
65         }
66         printf("%lld
", ans);
67     }
68     return 0;
69 }
View Code

F    kingdom

留坑。

G    Matrix

留坑。

H    Mountain

水。

 1 #include <bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 #define N 1010
 6  
 7 int n;
 8 int arr[N];
 9  
10 int main()
11 {
12     while(~scanf("%d", &n))
13     {
14         for(int i = 1; i <= n; ++i)  scanf("%d", arr + i);
15         int ans = 0;
16         for(int i = 1; i <= n; ++i)
17         {
18             ans = max(ans, arr[i]);
19         }
20         ans = ans * 2;
21         printf("%d
", ans);
22     }
23     return 0;
24 }
View Code

I    清明梦超能力者黄YY

思路:树链剖分维护u->v 路径上染色次数,倒着操作,每次找有没有第k次染色的点,有的话拿出来更新的答案,并且把那个点的然后次数置位-INF, 每个点最多拿出来一次

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define N 100010
  5 #define INF 0x3f3f3f3f
  6  
  7 int n, m, k;
  8 vector <int> G[N];
  9 int ans[N];
 10  
 11 struct QUE
 12 {
 13     int u, v, c;
 14     void scan()
 15     {
 16         scanf("%d%d%d", &u, &v, &c);
 17     }
 18 }que[N];
 19  
 20 int top[N], fa[N], deep[N], num[N], p[N], fp[N],son[N], pos;
 21  
 22 void Init()
 23 {
 24     memset(son, -1, sizeof son);
 25     pos = 0;
 26     fa[1] = 1, deep[1] = 0;
 27 }
 28  
 29 void DFS(int u)
 30 {
 31     num[u] = 1;
 32     for (auto v : G[u]) if (v != fa[u])
 33     {
 34         fa[v] = u; deep[v] = deep[u] + 1;
 35         DFS(v); num[u] += num[v];
 36         if (son[u] == -1 || num[v] > num[son[u]])
 37             son[u] = v;
 38     }
 39 }
 40  
 41 void getpos(int u, int sp)
 42 {
 43     top[u] = sp;
 44     p[u] = ++pos;
 45     fp[pos] = u;
 46     if (son[u] == -1) return;
 47     getpos(son[u], sp);
 48     for (auto v : G[u]) if (v != son[u] && v != fa[u])
 49         getpos(v, v);
 50 }
 51  
 52 struct SEG
 53 {
 54     struct node
 55     {
 56         int l, r;
 57         int lazy, Max, pos;
 58         node () {}
 59         node (int _l, int _r)
 60         {
 61             l = _l, r = _r;
 62             Max = 0;
 63             pos = _l;
 64             lazy = 0;
 65         }
 66     }a[N << 2];
 67  
 68     void pushup(int id)
 69     {
 70         if (a[id << 1].Max > a[id << 1 | 1].Max)
 71         {
 72             a[id].Max = a[id << 1].Max;
 73             a[id].pos = a[id << 1].pos;
 74         }  
 75         else
 76         {
 77             a[id].Max = a[id << 1 | 1].Max;
 78             a[id].pos = a[id << 1 | 1].pos;
 79         }
 80     }
 81  
 82     void pushdown(int id)
 83     {
 84         if (a[id].l >= a[id].r) return;
 85         if (a[id].lazy)
 86         {
 87             int lazy = a[id].lazy; a[id].lazy = 0;
 88             a[id << 1].lazy += lazy;
 89             a[id << 1 | 1].lazy += lazy;
 90             a[id << 1].Max += lazy;
 91             a[id << 1 | 1].Max += lazy;
 92         }
 93     }
 94  
 95     void build(int id, int l, int r)
 96     {
 97         a[id] = node(l, r);
 98         if (l == r) return;
 99         int mid = (l + r) >> 1;
100         build(id << 1, l, mid);
101         build(id << 1 | 1, mid + 1, r);
102         pushup(id);
103     }
104  
105     void update(int id, int l, int r, int val)
106     {
107         if (a[id].l >= l && a[id].r <= r)
108         {
109             a[id].Max += val;
110             a[id].lazy += val;
111             return;
112         }
113         pushdown(id);
114         int mid = (a[id].l + a[id].r) >> 1;
115         if (l <= mid) update(id << 1, l, r, val);
116         if (r > mid) update(id << 1 | 1, l, r, val);
117         pushup(id);
118     }
119 }segtree;
120  
121 void change(int u, int v, int val)
122 {
123     int fu = top[u], fv = top[v];
124     while (fu != fv)
125     {
126         if (deep[fu] < deep[fv])
127         {
128             swap(fu, fv);
129             swap(u, v);
130         }
131         int l = p[fu], r = p[u];
132         segtree.update(1, l, r, 1);
133         while (1)
134         {
135 //          puts("bug");
136             if (segtree.a[1].Max < k) break;
137             int pos = segtree.a[1].pos;
138 //          cout << pos << " " << segtree.a[1].Max << endl;
139             ans[fp[pos]] = val;
140             segtree.update(1, pos, pos, -INF);
141 //          cout << pos << " " << segtree.a[1].Max << endl;
142         }
143         u = fa[fu], fu = top[u];
144     }
145     if (deep[u] > deep[v]) swap(u, v);
146     int l = p[u], r = p[v];
147 //  printf("%d %d
", l, r);
148     segtree.update(1, l, r, 1);
149     while (1)
150     {
151         if (segtree.a[1].Max < k) break;
152         int pos = segtree.a[1].pos;
153 //      cout << pos << endl;
154         ans[fp[pos]] = val;
155 //      cout << segtree.a[1].pos << " " << segtree.a[1].Max << endl;
156         segtree.update(1, pos, pos, -INF);
157 //      cout << segtree.a[1].pos << " " << segtree.a[1].Max << endl;
158 //      puts("...................");
159     }
160 }
161  
162 int main()
163 {
164     while (scanf("%d%d%d", &n, &m, &k) != EOF)
165     {
166         Init();
167         for (int i = 1, u, v; i < n; ++i)
168         {
169             scanf("%d%d", &u, &v);
170             G[u].push_back(v);
171             G[v].push_back(u);
172         } DFS(1), getpos(1, 1);
173 //      for (int i = 1; i <= n; ++i) printf("%d %d %d
", i, p[i], fp[i]);
174         for (int i = 1; i <= m; ++i) que[i].scan();
175         memset(ans, 0, sizeof ans);
176         segtree.build(1, 1, n);
177         for (int i = m; i >= 1; --i) change(que[i].u, que[i].v, que[i].c);
178         for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], " 
"[i == n]);
179     }
180     return 0;
181 }
View Code

J    最短路

思路一(应该不是正解):对于环内的点,拿出来,分别跑Dijkstra, 这样的点数应该在100左右,然后每次询问的时候更新答案。但是有一点奇怪的是,用并查集找出环内的点,就不会T,标记访问直接DFS找就会T。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 using pii = pair <int, int>;
  4  
  5 #define N 101010
  6  
  7 const int INF = 0x3f3f3f3f;
  8  
  9 template <class T>
 10 inline bool scan_d(T &ret)
 11 {
 12     char c; int sgn;
 13     if (c = getchar(), c == EOF) return 0;
 14     while (c != '-' && (c < '0' || c > '9')) c = getchar();
 15     sgn = (c == '-') ? -1 : 1;
 16     ret = (c == '-') ? 0 : (c - '0');
 17     while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
 18     ret *= sgn;
 19     return 1;
 20 }
 21  
 22 inline void out(int x)
 23 {
 24     if (x / 10) out(x / 10);
 25     putchar(x % 10 + '0');
 26 }
 27  
 28 vector <int> G[N];
 29 int vis[N], deep[N], stk[N], top;
 30  
 31 struct ST
 32 {
 33     int mm[N << 1];
 34     int dp[N << 1][20];
 35     int rmq[N << 1];
 36     int F[N << 1], P[N], cnt;
 37  
 38     void Init(int n)
 39     {
 40         mm[0] = -1;
 41         for (int i = 1; i <= n; ++i)
 42         {
 43             mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
 44             dp[i][0] = i;
 45         }
 46         for (int j = 1; j <= mm[n]; ++j)
 47             for (int i = 1; i + (1 << j) - 1 <= n; ++i)
 48                 dp[i][j] = rmq[dp[i][j - 1]] < rmq[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1];
 49     }
 50  
 51     int query(int a, int b)
 52     {
 53         if (a > b) swap(a, b);
 54         int k = mm[b - a + 1];
 55         return rmq[dp[a][k]] <= rmq[dp[b - (1 << k) + 1][k]] ? dp[a][k] : dp[b - (1 << k) + 1][k];
 56     }
 57  
 58     void DFS(int u, int fa)
 59     {
 60         F[++cnt] = u;
 61         rmq[cnt] = deep[u];
 62         P[u] = cnt;
 63         vis[u] = 1;
 64         for (auto v : G[u]) if (v != fa)
 65         {
 66             if (vis[v])
 67             {
 68                 stk[++top] = v;
 69                 continue;
 70             }
 71             deep[v] = deep[u] + 1;
 72             DFS(v, u);
 73             F[++cnt] = u;
 74             rmq[cnt] = deep[u];
 75         }
 76     }
 77  
 78     void init(int root, int node_num)
 79     {
 80         cnt = 0;
 81         deep[1] = 0;
 82         DFS(root, root);
 83         Init(2 * node_num - 1);
 84     }
 85  
 86     int query_lca(int u, int v)
 87     {
 88         return F[query(P[u], P[v])];
 89     }
 90 }st;
 91  
 92 int n, m;
 93 int dis[210][N];
 94 queue <int> q;
 95  
 96 void Dijkstra(int it, int st)
 97 {
 98     for (int i = 1; i <= n; ++i)
 99     {
100         vis[i] = 0;
101         dis[it][i] = INF;
102     }
103     dis[it][st] = 0;
104     q.push(st);
105     while (!q.empty())
106     {
107         int u = q.front(); q.pop();
108         if (vis[u]) continue;
109         vis[u] = 1;
110         for (auto v : G[u])
111         {
112             if (dis[it][v] > dis[it][u] + 1)
113             {
114                 dis[it][v] = dis[it][u] + 1;
115                 q.push(v);
116             }
117         }
118     }
119 }
120  
121 vector <pii> tmp;
122  
123 int pre[N];
124  
125 int find(int x)
126 {
127     if (x != pre[x])
128         pre[x] = find(pre[x]);
129     return pre[x];
130 }
131  
132 void Run()
133 {
134     while (scan_d(n), scan_d(m))
135     {
136         for (int i = 1; i <= n; ++i) pre[i] = i; top = 0;
137         for (int i = 1, u, v; i <= m; ++i)
138         {
139             scan_d(u), scan_d(v);
140             int fu = find(u), fv = find(v);
141             if (fu == fv)
142             {
143                 tmp.emplace_back(u, v);
144                 stk[++top] = u;
145             }
146             else
147             {
148                 G[u].push_back(v);
149                 G[v].push_back(u);
150                 pre[fu] = fv;
151             }
152         }
153         st.init(1, n); 
154         sort(stk + 1, stk + 1 + top);
155         int nn = unique(stk + 1, stk + 1 + top) - stk - 1;
156         for (auto it : tmp)
157         {
158             G[it.first].push_back(it.second);
159             G[it.second].push_back(it.first);
160         }
161         for (int i = 1; i <= nn; ++i) Dijkstra(i, stk[i]);
162         int q;
163         scan_d(q);
164         while (q--)
165         {
166             int u, v;
167             scan_d(u), scan_d(v);
168             int root = st.query_lca(u, v);
169             int ans = deep[u] + deep[v] - 2 * deep[root];
170             for (int i = 1; i <= nn; ++i)
171                 ans = min(ans, dis[i][u] + dis[i][v]);
172             out(ans), putchar('
');
173         }
174     }
175 }
176 int main()
177 {
178     #ifdef LOCAL
179         freopen("Test.in", "r", stdin);
180     #endif
181  
182     Run();
183     return 0;
184 }
View Code

K    排序

留坑。

原文地址:https://www.cnblogs.com/Dup4/p/9747773.html