题面

题面

题解

观察到题目中的 “内陆经济环” 不好处理,因此我们把它拆成 “内陆经济链”。

对于1号节点,我们创建一个它的复制节点n + 1号节点,这个节点继承1号节点的所有边,可以发现,一个1到1的内陆经济环,和一个1到n + 1的内陆经济链是等价的,因此我们只需要考虑如何在一个变化的图上维护一个点到另一个点的最大xor和即可。

观察到删边只会删去后来加入的边,所以就很好处理了,我们用线段树分治(时间分治)来维护。

具体求从1到n + 1的最大xor和的方法参见此题(是一个常见套路,就不在赘述了):[WC2011]最大XOR和路径 线性基

于是我们的目的仅仅是维护当前图中所有简单环构成的线性基。

因为线段树分治最深也就log,所以同时维护log个线性基的时间空间都还是可承受的。

因此我们每到一个新节点就建一个新的线性基,然后加入新增的环,退出时再删去即可。

考虑如何快速求新增的环。

因为在dfs树上,一条非树边代表一个简单环,所以一个新增的,连接x ---> y 的边最多带来一个新环,而这个新环,肯定是经过这条新边,从x走到y,再走回x的路径所构成的一个环。

因为xor的特性,所以我们可以用x到rot的路径 + y到rot的路径 + 新边来异或出这个环的异或值。

因此我们只需要知道一个点新增了哪些边就可以了。

#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 550
#define ac 2100
#define maxn 8000
#define maxm 2010000 int n, m, all, cnt;
int dead[ac], start[ac], id[ac];
int Head[AC], date[ac], Next[ac], tot;
bitset<1100> len[ac], ans[ac], val[AC], link[maxn];
struct road{int x, y, id;bitset<1100> v;}way[ac];//注意一条边会且只会带来一个环(因为原图联通)
bool vis[AC];
char ss[ac]; //int s[AC], top;//存下待分配的线性基编号
struct basis{//第几层就用第几个线性基
bitset<1100> f[1100];//第1000位为最高位
void clear() {for(R i = 1; i <= 1000; i += 2) f[i] = f[i + 1] = 0;} void ins(bitset<1100> x)
{
for(R i = 1000; i; i --)
{
if(!x[i]) continue;
if(f[i] == 0) {f[i] = x; break;}
else x ^= f[i];
}
} }f[50];//最多同时用到log个线性基 inline int read()
{
int x = 0;char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
} /*inline void add_new(int f, int w)//f为线段树上的一个点,w是一条边的编号
{date_[++ tot_] = w, Next_[tot_] = Head_[f], Head_[f] = tot_;}*/ inline void add(int f, int w, bitset<1100> S)
{
date[++ tot] = w, Next[tot] = Head[f], Head[f] = tot, len[tot] = S;
date[++ tot] = f, Next[tot] = Head[w], Head[w] = tot, len[tot] = S;
} void dfs(int x, bitset<1100> have)//找最初的环,
{
vis[x] = true, val[x] = have;
for(R i = Head[x]; i; i = Next[i])
{
int now = date[i];
if(vis[now]) f[0].ins(have ^ len[i] ^ val[now]);
else dfs(now, have ^ len[i]);
}
} void change(int x, int l, int r, int ll, int rr, int w)//给[ll, rr]加入一条边,其编号为w
{
if(l == ll && r == rr){link[x][w] = true; return ;}
int mid = (l + r) >> 1;
if(rr <= mid) change(x << 1, l, mid, ll, rr, w);
else if(ll > mid) change((x << 1) + 1, mid + 1, r, ll, rr, w);
else
{
change(x << 1, l, mid, ll, mid, w);
change((x << 1) + 1, mid + 1, r, mid + 1, rr, w);
}
} void solve(int x, int l, int r, int dep)
{
f[dep] = f[dep - 1];
for(R i = 1; i <= all; i ++)
if(link[x][i]) f[dep].ins(val[way[i].x] ^ val[way[i].y] ^ way[i].v);
if(l == r)
{
ans[l] = val[n + 1];
for(R i = 1000; i; i --)
if(ans[l][i] == 0) ans[l] ^= f[dep].f[i];
return ;
}
int mid = (l + r) >> 1;
solve(x << 1, l, mid, dep + 1);
solve((x << 1) + 1, mid + 1, r, dep + 1);
} bitset<1100> get()
{
bitset<1100> tmp;
scanf("%s", ss + 1); int t = strlen(ss + 1);
for(R j = t, l = 1; j; j --, l ++) tmp[l] = (ss[j] == '1'); //存下边权
return tmp;
} void pre()
{
n = read(), m = read(), all = read();
bitset<1100> tmp;
for(R i = 1; i <= m; i ++)
{
int x = read(), y = read();
if(x > y) swap(x, y);
tmp = get();
add(x, y, tmp);
if(x == 1) add(n + 1, y, tmp);
}
} void build()
{
for(R i = 1; i <= all; i ++)
{
scanf("%s", ss + 1);
if(ss[1] == 'A') //加边
{
id[++ cnt] = i;//id[x]存下边x当前是谁在承受修改
start[i] = i, dead[i] = all;
way[i].x = read(), way[i].y = read(), way[i].v = get();
}
else if(ss[2] == 'a') {dead[id[read()]] = i - 1;}//删边
else //修改边权,看做删去一条旧边生成一条新边,并且新边承担后面旧边的修改
{
int x = read();//承担旧边的修改,并删除旧边
way[i] = way[id[x]], way[i].v = get();
start[i] = i, dead[i] = all, dead[id[x]] = i - 1, id[x] = i;//除了初始化id[x]外,其他的地方都要用到id[x]
}//所以id[x] = i放在最后面修改,在前面的x都要用id[x]代替
}
for(R i = 1; i <= all; i ++)
if(start[i]) change(1, 1, all, start[i], dead[i], i);
} void work()
{
for(R i = 1000; i; i --)
if(!ans[0][i]) ans[0] ^= f[0].f[i];
for(R i = 0; i <= all; i ++)
{
int l = 1000;
while(!ans[i][l] && l) -- l;
for(R j = l; j; j --) printf("%c", (ans[i][j] == 1) ? '1' : '0');
if(!l) printf("0");
printf("\n");
}
} int main()
{
// freopen("in.in", "r", stdin);
pre();
dfs(1, ans[0]);//反正此时ans[0]是空的
build();
if(all) solve(1, 1, all, 1);
work();
// fclose(stdin);
return 0;
}

最新文章

  1. AI人工智能系列随笔
  2. C#-WebForm-纯HTML提交方式
  3. C和指针 第四章 习题
  4. 在Django中使用Mako模板
  5. Oracle - SQL 错误: ORA-00917: 缺失逗号
  6. apache 反向代理配置(ubuntu)
  7. Chef 自动化运维:开始“烹饪”
  8. 什么是TNB?如何买TNB?
  9. 前端笔记之jQuery(上)加载函数的区别&amp;对象&amp;操作HTML/CSS&amp;动画&amp;选择器
  10. Deep Learning.ai学习笔记_第三门课_结构化机器学习项目
  11. get_time
  12. [转]SPI通信原理简介
  13. UVALi 3263 That Nice Euler Circuit(几何)
  14. JSON数据的处理中的特殊字符
  15. nginx记录post数据日志
  16. 利用Python做绝地科学家(外挂篇)
  17. Phoenix安装配置
  18. AIX6.1用g++安装Poco-1.6.1-all
  19. python_基础算法
  20. is-subsequence

热门文章

  1. Elasticsearch6.2集群搭建
  2. MongoDB 极简实践入门
  3. CSP201312-3:最大的矩形
  4. vim—多行注释、取消多行注释
  5. Oracle 11g用exp无法导出空表的处理方法
  6. 上午做的第一个安卓app
  7. tensorflow之分类学习
  8. timestamp 学习
  9. lintcode-384-最长无重复字符的子串
  10. HashMap和HashTable源码分析