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 }

你可能感兴趣的:(2012)