BZOJ 2816 [ZJOI2012]网络
题目大意:
一个无向图, 每条边有颜色, 颜色不超过10种. 从一个点出发的同色边不超过2条, 且不存在同色环. 操作有修改一个点的权值, 修改某条边的颜色, 询问两点之间由某种颜色构成的简单路径上权值最大值.
简要分析:
围观这道题...发现相同颜色的构成了一坨链, 操作就是连接两条链, 断开一条链, 询问同一链上两点间最大值.
赤裸裸的数据结构题. 用Splay维护所有链, 可以很方便的断开和连接. 注意连接的时候可能会需要把其中一根链反转, 这个是经典操作, 打标记就可以了.
一个trick就是询问的两个点相同...我的程序要特判...晕...加上读入优化后速度还可以. 另外这题不是链而是树的话也是可以捉的...只不过要用LCT了...
哦, 题面可以去noi吧的自助资源站找.
代码实现:
View Code
1 #include <cstdio>
2 #include <cstring>
3 #include <utility>
4 #include <map>
5 #include <algorithm>
6
7 using std::pair;
8 using std::make_pair;
9 using std::map;
10 using std::max;
11 using std::min;
12 using std::swap;
13
14 typedef pair<int, int> Edge;
15 map<Edge, int> col_idx;
16 const int kMaxN = 10000, kMaxM = 200000, kMaxC = 10;
17 int n, m, col_kind, q, w[kMaxN];
18 int cnt, begin[kMaxN], end[kMaxM], next[kMaxM], col[kMaxM];
19 int col_cnt[kMaxN][kMaxC];
20 bool col_vis[kMaxN][kMaxC];
21
22 #undef NULL
23 #define NULL Node::nil
24
25 struct Info {
26 int v;
27 Info() : v(0) {}
28 Info(int v_) : v(v_) {}
29 };
30
31 inline Info operator + (const Info &a, const Info &b) {
32 return Info(max(a.v, b.v));
33 }
34
35 struct Mark {
36 bool rev;
37 Mark() : rev(false) {}
38 Mark(bool rev_) : rev(rev_) {}
39 };
40
41 struct Node {
42 Info ori, acc;
43 Mark mark;
44 Node *son[2], *par;
45 Node() {
46 son[0] = son[1] = par = NULL;
47 }
48 void update() {
49 acc = son[0]->acc + ori + son[1]->acc;
50 }
51 static Node nil_ins, *nil;
52 } node_pool[kMaxN * kMaxC], *node[kMaxN][kMaxC];
53
54 Node Node::nil_ins;
55 Node *Node::nil = &nil_ins;
56
57 void DoPush(Node *pos, const Mark &mark) {
58 if (pos != NULL && mark.rev) {
59 pos->mark.rev ^= 1;
60 swap(pos->son[0], pos->son[1]);
61 }
62 }
63
64 void Push(Node *pos) {
65 if (pos != NULL && pos->mark.rev) {
66 DoPush(pos->son[0], pos->mark.rev);
67 DoPush(pos->son[1], pos->mark.rev);
68 pos->mark.rev = false;
69 }
70 }
71
72 void Rot(Node *pos, bool t) {
73 Node *tptr = pos->son[t], *tmp = NULL;
74 pos->son[t] = tptr->son[!t];
75 if ((tmp = tptr->son[!t]) != NULL) tmp->par = pos;
76 tptr->son[!t] = pos;
77 if ((tmp = pos->par) != NULL) tmp->son[tmp->son[1] == pos] = tptr;
78 pos->par = tptr;
79 tptr->par = tmp;
80 }
81
82 void PushTo(Node *pos) {
83 static Node *stack[kMaxN];
84 static int stop;
85 stop = 0;
86 while (pos != NULL) {
87 stack[stop ++] = pos;
88 pos = pos->par;
89 }
90 while (stop) {
91 Push(stack[stop - 1]);
92 -- stop;
93 }
94 }
95
96 void Splay(Node *pos, Node *des = NULL) {
97 PushTo(pos);
98 Node register *ngra, *npar;
99 bool register d1, d2;
100 while (pos != des && (npar = pos->par) != des) {
101 ngra = npar->par;
102 if (ngra == des) Rot(npar, npar->son[1] == pos), npar->update();
103 else {
104 if ((d1 = (ngra->son[1] == npar)) == (d2 = (npar->son[1] == pos))) Rot(ngra, d1), Rot(npar, d2);
105 else Rot(npar, d2), Rot(ngra, d1);
106 ngra->update(), npar->update();
107 }
108 }
109 pos->update();
110 }
111
112 void AddEdge(int u, int v, int c) {
113 next[cnt] = begin[u];
114 begin[u] = cnt;
115 end[cnt] = v;
116 col[cnt ++] = c;
117 }
118
119 Node *BuildTree(int l, int r, Node *npar, int *q, int c) {
120 if (l > r) return NULL;
121 int mid = (l + r) >> 1;
122 Node *res = node[q[mid]][c];
123 res->par = npar;
124 res->ori.v = res->acc.v = w[q[mid]];
125 res->son[0] = BuildTree(l, mid - 1, res, q, c);
126 res->son[1] = BuildTree(mid + 1, r, res, q, c);
127 res->update();
128 return res;
129 }
130
131 void FindChain(int u, int c) {
132 static int q[kMaxN], qh, qt;
133 qh = qt = 0;
134 q[qt ++] = u;
135 col_vis[u][c] = true;
136 while (qh < qt) {
137 int u = q[qh ++];
138 for (int now = begin[u], v; now != -1; now = next[now])
139 if (col[now] == c && !col_vis[v = end[now]][c]) {
140 col_vis[v][c] = true;
141 q[qt ++] = v;
142 break;
143 }
144 }
145 BuildTree(0, qt - 1, NULL, q, c);
146 }
147
148 bool IsConnectedByAColor(Node *u, Node *v) {
149 Splay(u), Splay(v);
150 return (u->par != NULL);
151 }
152
153 void Split(Node *u, Node *v) {
154 Splay(u), Splay(v, u);
155 v->par = NULL;
156 u->son[u->son[1] == v] = NULL;
157 u->update();
158 }
159
160 void Merge(Node *u, Node *v) {
161 Splay(u), Splay(v);
162 if (u->son[1] == NULL && v->son[0] == NULL) u->son[1] = v;
163 else if (u->son[0] == NULL && v->son[1] == NULL) u->son[0] = v;
164 else if (u->son[0] == NULL) {
165 DoPush(u, Mark(true));
166 Push(u);
167 u->son[1] = v;
168 }
169 else {
170 DoPush(u, Mark(true));
171 Push(u);
172 u->son[0] = v;
173 }
174 v->par = u;
175 u->update();
176 }
177
178 int AskMax(Node *u, Node *v) {
179 Splay(u), Splay(v, u);
180 bool t = (u->son[1] == v);
181 return (u->son[t]->son[!t]->acc + u->ori + v->ori).v;
182 }
183
184 inline bool IsConnectedByAColor(int u, int v, int c) {
185 return IsConnectedByAColor(node[u][c], node[v][c]);
186 }
187
188 inline void Split(int u, int v, int c) {
189 Split(node[u][c], node[v][c]);
190 }
191
192 inline void Merge(int u, int v, int c) {
193 Merge(node[u][c], node[v][c]);
194 }
195
196 inline int AskMax(int u, int v, int c) {
197 return AskMax(node[u][c], node[v][c]);
198 }
199
200 int main() {
201 memset(begin, -1, sizeof(begin));
202 scanf("%d%d%d%d", &n, &m, &col_kind, &q);
203 for (int i = 0; i < n; ++ i)
204 for (int j = 0; j < col_kind; ++ j)
205 node[i][j] = &node_pool[i * col_kind + j];
206 for (int i = 0; i < n; ++ i) scanf("%d", &w[i]);
207 for (int u, v, c; m --; ) {
208 scanf("%d%d%d", &u, &v, &c);
209 -- u, -- v;
210 AddEdge(u, v, c);
211 AddEdge(v, u, c);
212 ++ col_cnt[u][c];
213 ++ col_cnt[v][c];
214 col_idx[make_pair(min(u, v), max(u, v))] = c;
215 }
216 for (int i = 0; i < col_kind; ++ i)
217 for (int j = 0; j < n; ++ j)
218 if (col_cnt[j][i] == 1 && !col_vis[j][i]) FindChain(j, i);
219 for (int cmd, u, v, c; q --; ) {
220 scanf("%d", &cmd);
221 if (cmd == 0) {
222 scanf("%d%d", &u, &v);
223 -- u;
224 w[u] = v;
225 for (int i = 0; i < col_kind; ++ i) {
226 Splay(node[u][i]);
227 node[u][i]->ori.v = node[u][i]->acc.v = v;
228 node[u][i]->update();
229 }
230 }
231 else if (cmd == 1) {
232 scanf("%d%d%d", &u, &v, &c);
233 -- u, -- v;
234 if (u > v) swap(u, v);
235 if (!col_idx.count(make_pair(u, v))) printf("No such edge.\n");
236 else {
237 int ori_c = col_idx[make_pair(u, v)];
238 if (c == ori_c) printf("Success.\n");
239 else if (col_cnt[u][c] + 1 > 2 || col_cnt[v][c] + 1 > 2) printf("Error 1.\n");
240 else if (IsConnectedByAColor(u, v, c)) printf("Error 2.\n");
241 else {
242 Split(u, v, ori_c);
243 Merge(u, v, c);
244 printf("Success.\n");
245 -- col_cnt[u][ori_c];
246 -- col_cnt[v][ori_c];
247 ++ col_cnt[u][c];
248 ++ col_cnt[v][c];
249 col_idx[make_pair(u, v)] = c;
250 }
251 }
252 }
253 else {
254 scanf("%d%d%d", &c, &u, &v);
255 -- u, -- v;
256 if (u == v) printf("%d\n", w[u]);
257 else if (!IsConnectedByAColor(u, v, c)) printf("-1\n");
258 else printf("%d\n", AskMax(u, v, c));
259 }
260 }
261 return 0;
262 }