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 }
posted @ 2012-06-02 17:11  zcwwzdjn  阅读(1633)  评论(0编辑  收藏  举报