题目大意:
一个无向图, 每条边有颜色, 颜色不超过10种. 从一个点出发的同色边不超过2条, 且不存在同色环. 操作有修改一个点的权值, 修改某条边的颜色, 询问两点之间由某种颜色构成的简单路径上权值最大值.
简要分析:
围观这道题...发现相同颜色的构成了一坨链, 操作就是连接两条链, 断开一条链, 询问同一链上两点间最大值.
赤裸裸的数据结构题. 用Splay维护所有链, 可以很方便的断开和连接. 注意连接的时候可能会需要把其中一根链反转, 这个是经典操作, 打标记就可以了.
一个trick就是询问的两个点相同...我的程序要特判...晕...加上读入优化后速度还可以. 另外这题不是链而是树的话也是可以捉的...只不过要用LCT了...
哦, 题面可以去noi吧的自助资源站找.
代码实现:
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 }