您的位置:首页 > 理论基础 > 计算机网络

BZOJ 2816 [ZJOI2012]网络

2012-06-02 17:11 330 查看
题目大意:

一个无向图, 每条边有颜色, 颜色不超过10种. 从一个点出发的同色边不超过2条, 且不存在同色环. 操作有修改一个点的权值, 修改某条边的颜色, 询问两点之间由某种颜色构成的简单路径上权值最大值.

简要分析:

围观这道题...发现相同颜色的构成了一坨链, 操作就是连接两条链, 断开一条链, 询问同一链上两点间最大值.

赤裸裸的数据结构题. 用Splay维护所有链, 可以很方便的断开和连接. 注意连接的时候可能会需要把其中一根链反转, 这个是经典操作, 打标记就可以了.

一个trick就是询问的两个点相同...我的程序要特判...晕...加上读入优化后速度还可以. 另外这题不是链而是树的话也是可以捉的...只不过要用LCT了...

哦, 题面可以去noi吧的自助资源站找.

代码实现:

View Code

#include <cstdio>
#include <cstring>
#include <utility>
#include <map>
#include <algorithm>

using std::pair;
using std::make_pair;
using std::map;
using std::max;
using std::min;
using std::swap;

typedef pair<int, int> Edge;
map<Edge, int> col_idx;
const int kMaxN = 10000, kMaxM = 200000, kMaxC = 10;
int n, m, col_kind, q, w[kMaxN];
int cnt, begin[kMaxN], end[kMaxM], next[kMaxM], col[kMaxM];
int col_cnt[kMaxN][kMaxC];
bool col_vis[kMaxN][kMaxC];

#undef NULL
#define NULL Node::nil

struct Info {
int v;
Info() : v(0) {}
Info(int v_) : v(v_) {}
};

inline Info operator + (const Info &a, const Info &b) {
return Info(max(a.v, b.v));
}

struct Mark {
bool rev;
Mark() : rev(false) {}
Mark(bool rev_) : rev(rev_) {}
};

struct Node {
Info ori, acc;
Mark mark;
Node *son[2], *par;
Node() {
son[0] = son[1] = par = NULL;
}
void update() {
acc = son[0]->acc + ori + son[1]->acc;
}
static Node nil_ins, *nil;
} node_pool[kMaxN * kMaxC], *node[kMaxN][kMaxC];

Node Node::nil_ins;
Node *Node::nil = &nil_ins;

void DoPush(Node *pos, const Mark &mark) {
if (pos != NULL && mark.rev) {
pos->mark.rev ^= 1;
swap(pos->son[0], pos->son[1]);
}
}

void Push(Node *pos) {
if (pos != NULL && pos->mark.rev) {
DoPush(pos->son[0], pos->mark.rev);
DoPush(pos->son[1], pos->mark.rev);
pos->mark.rev = false;
}
}

void Rot(Node *pos, bool t) {
Node *tptr = pos->son[t], *tmp = NULL;
pos->son[t] = tptr->son[!t];
if ((tmp = tptr->son[!t]) != NULL) tmp->par = pos;
tptr->son[!t] = pos;
if ((tmp = pos->par) != NULL) tmp->son[tmp->son[1] == pos] = tptr;
pos->par = tptr;
tptr->par = tmp;
}

void PushTo(Node *pos) {
static Node *stack[kMaxN];
static int stop;
stop = 0;
while (pos != NULL) {
stack[stop ++] = pos;
pos = pos->par;
}
while (stop) {
Push(stack[stop - 1]);
-- stop;
}
}

void Splay(Node *pos, Node *des = NULL) {
PushTo(pos);
Node register *ngra, *npar;
bool register d1, d2;
while (pos != des && (npar = pos->par) != des) {
ngra = npar->par;
if (ngra == des) Rot(npar, npar->son[1] == pos), npar->update();
else {
if ((d1 = (ngra->son[1] == npar)) == (d2 = (npar->son[1] == pos))) Rot(ngra, d1), Rot(npar, d2);
else Rot(npar, d2), Rot(ngra, d1);
ngra->update(), npar->update();
}
}
pos->update();
}

void AddEdge(int u, int v, int c) {
next[cnt] = begin[u];
begin[u] = cnt;
end[cnt] = v;
col[cnt ++] = c;
}

Node *BuildTree(int l, int r, Node *npar, int *q, int c) {
if (l > r) return NULL;
int mid = (l + r) >> 1;
Node *res = node[q[mid]][c];
res->par = npar;
res->ori.v = res->acc.v = w[q[mid]];
res->son[0] = BuildTree(l, mid - 1, res, q, c);
res->son[1] = BuildTree(mid + 1, r, res, q, c);
res->update();
return res;
}

void FindChain(int u, int c) {
static int q[kMaxN], qh, qt;
qh = qt = 0;
q[qt ++] = u;
col_vis[u][c] = true;
while (qh < qt) {
int u = q[qh ++];
for (int now = begin[u], v; now != -1; now = next[now])
if (col[now] == c && !col_vis[v = end[now]][c]) {
col_vis[v][c] = true;
q[qt ++] = v;
break;
}
}
BuildTree(0, qt - 1, NULL, q, c);
}

bool IsConnectedByAColor(Node *u, Node *v) {
Splay(u), Splay(v);
return (u->par != NULL);
}

void Split(Node *u, Node *v) {
Splay(u), Splay(v, u);
v->par = NULL;
u->son[u->son[1] == v] = NULL;
u->update();
}

void Merge(Node *u, Node *v) {
Splay(u), Splay(v);
if (u->son[1] == NULL && v->son[0] == NULL) u->son[1] = v;
else if (u->son[0] == NULL && v->son[1] == NULL) u->son[0] = v;
else if (u->son[0] == NULL) {
DoPush(u, Mark(true));
Push(u);
u->son[1] = v;
}
else {
DoPush(u, Mark(true));
Push(u);
u->son[0] = v;
}
v->par = u;
u->update();
}

int AskMax(Node *u, Node *v) {
Splay(u), Splay(v, u);
bool t = (u->son[1] == v);
return (u->son[t]->son[!t]->acc + u->ori + v->ori).v;
}

inline bool IsConnectedByAColor(int u, int v, int c) {
return IsConnectedByAColor(node[u][c], node[v][c]);
}

inline void Split(int u, int v, int c) {
Split(node[u][c], node[v][c]);
}

inline void Merge(int u, int v, int c) {
Merge(node[u][c], node[v][c]);
}

inline int AskMax(int u, int v, int c) {
return AskMax(node[u][c], node[v][c]);
}

int main() {
memset(begin, -1, sizeof(begin));
scanf("%d%d%d%d", &n, &m, &col_kind, &q);
for (int i = 0; i < n; ++ i)
for (int j = 0; j < col_kind; ++ j)
node[i][j] = &node_pool[i * col_kind + j];
for (int i = 0; i < n; ++ i) scanf("%d", &w[i]);
for (int u, v, c; m --; ) {
scanf("%d%d%d", &u, &v, &c);
-- u, -- v;
AddEdge(u, v, c);
AddEdge(v, u, c);
++ col_cnt[u][c];
++ col_cnt[v][c];
col_idx[make_pair(min(u, v), max(u, v))] = c;
}
for (int i = 0; i < col_kind; ++ i)
for (int j = 0; j < n; ++ j)
if (col_cnt[j][i] == 1 && !col_vis[j][i]) FindChain(j, i);
for (int cmd, u, v, c; q --; ) {
scanf("%d", &cmd);
if (cmd == 0) {
scanf("%d%d", &u, &v);
-- u;
w[u] = v;
for (int i = 0; i < col_kind; ++ i) {
Splay(node[u][i]);
node[u][i]->ori.v = node[u][i]->acc.v = v;
node[u][i]->update();
}
}
else if (cmd == 1) {
scanf("%d%d%d", &u, &v, &c);
-- u, -- v;
if (u > v) swap(u, v);
if (!col_idx.count(make_pair(u, v))) printf("No such edge.\n");
else {
int ori_c = col_idx[make_pair(u, v)];
if (c == ori_c) printf("Success.\n");
else if (col_cnt[u][c] + 1 > 2 || col_cnt[v][c] + 1 > 2) printf("Error 1.\n");
else if (IsConnectedByAColor(u, v, c)) printf("Error 2.\n");
else {
Split(u, v, ori_c);
Merge(u, v, c);
printf("Success.\n");
-- col_cnt[u][ori_c];
-- col_cnt[v][ori_c];
++ col_cnt[u][c];
++ col_cnt[v][c];
col_idx[make_pair(u, v)] = c;
}
}
}
else {
scanf("%d%d%d", &c, &u, &v);
-- u, -- v;
if (u == v) printf("%d\n", w[u]);
else if (!IsConnectedByAColor(u, v, c)) printf("-1\n");
else printf("%d\n", AskMax(u, v, c));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: