传送门
题解:
只提一下记个要用的性质,证明去集训队论文里面看。
- 满足题意限制的图称为广义串并联图。
- 任何一个广义串并联图,去掉重边之后边数不超过点数的两倍。
- 任何一个广义串并联图可以由如下的方式构造:初始只有一个点,每次可以选择 1)加一个点,并和图中原有点连一条边,2)选择两个直接相连的点,新加一个点与这两个点相连,并且可以选择是否删去原来连接这两个点的边。
当然广义串并联图也是平面图,不过这个性质这道题用不到。
而且广义串并联图上还可以出奇妙的 O ( n 2 ) O(n^2) O(n2) 异或高斯消元题(好几个月之前的idea了),等我退役之后可能会出出来吧。
那么就需要做的事情就很明显了,我们考虑对构造反着来,直到图只剩下一个节点即可。
需要支持的操作有1)删一个度数为 1 1 1 的点,2)缩一个度数为 2 2 2 的点并消去重边。
容易发现每个点维护两种颜色的权值,每条边要维护两边四种情况的权值,然后就可以DP了。
加上修改,考虑动态DP。
乍一看是没法用矩阵维护的,一条边的四个权值其实需要用 1 × 4 1\times 4 1×4 的向量而不是 2 × 2 2\times 2 2×2 的矩阵来维护。
然后随便维护一下动态DP就行了,算轻儿子之和分类讨论有点麻烦。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=3e7+7;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
inline ll gl(){return get_integer<ll>();}
char obuf[(int)(3e7+7)],*oh=obuf,ch[23];
template<typename T>void print(T a,char c){
if(a<0)*oh++='-',a=-a;int tl=0;
do ch[++tl]=a%10; while(a/=10);
while(tl)*oh++=ch[tl--]^48;*oh++=c;
}struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;
}using IO::gi;
using IO::gl;
using IO::print;
using std::cerr;
using std::cout;
#define fi first
#define se second
template<typename T>void cmax(T &a,cs T &b){a<b?a=b:a;}
cs int N=1e5+7,M=N+N+1;
cs ll INF=1e12,I=-INF;
struct mat{
ll a[4][4];int r,c;
ll *operator[](int o){return a[o];}
cs ll *operator[](int o)cs{return a[o];}
};
mat operator*(cs mat &A,cs mat &B){
int r=A.r,m=A.c,c=B.c;
assert(B.r==A.c);
static mat C;C.r=r,C.c=c;
for(int re i=0;i<r;++i)
for(int re j=0;j<c;++j)
C[i][j]=I;
for(int re i=0;i<r;++i)
for(int re j=0;j<m;++j)if(A[i][j]>I)
for(int re k=0;k<c;++k)
cmax(C[i][k],A[i][j]+B[j][k]);
return C;
}
struct Edge{int u,v,v0,v1;}E[M+N];
int n,m,rt;
void gmat(int u,mat &A){
ll v0=E[u].v0,v1=E[u].v1;
if(u<=n){
A.r=2,A.c=1;A[0][0]=v0,A[1][0]=v1;
}else {
A.r=4,A.c=1;
A[0][0]=A[3][0]=v0;
A[1][0]=A[2][0]=v1;
}
}
namespace T{//Tree
cs int N=7e5+7;
int op[N],ch[N][3];
int sz[N],son[N],tg[N];
int el[N],nx[N];
void adde(int u,int v){
nx[v]=el[u],el[u]=v;
}
int node(int o,int c1,int c2=0,int c3=0){
int u=++rt;op[u]=o;
if(c3){
ch[u][2]=c3,adde(u,c3);sz[u]+=sz[c3];
if(sz[son[u]]<sz[c3])son[u]=c3,tg[u]=3;
}if(c2){
ch[u][1]=c2,adde(u,c2);sz[u]+=sz[c2];
if(sz[son[u]]<sz[c2])son[u]=c2,tg[u]=2;
}if(c1){
ch[u][0]=c1,adde(u,c1);sz[u]+=sz[c1];
if(sz[son[u]]<sz[c1])son[u]=c1,tg[u]=1;
}sz[u]++;return u;
}
int lsz[N],lc[N],rc[N],fa[N];
mat g[N],vl_son[N][2],prod[N];
int sm[N],st[N],tp,tg_son[N];
void calc_g(int u){
mat &G=g[u];
switch(op[u]){
case 0:{gmat(u,G);break;}
case 1:{
auto &t=vl_son[u][0];
ll a=t[0][0],b=t[1][0],c=t[2][0],d=t[3][0];
G={a,I,I,I,I,b,I,I,I,I,c,I,I,I,I,d,4,4};
break;
}case 2:{
G={0,I,I,I,I,I,0,I,I,0,I,I,I,I,I,0,4,4};
break;
}case 3:{
switch(tg[u]){
case 1:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
w[0][0]+v[0][0],w[1][0]+v[2][0],I,I,
w[0][0]+v[1][0],w[1][0]+v[3][0],I,I,
I,I,w[0][0]+v[0][0],w[1][0]+v[2][0],
I,I,w[0][0]+v[1][0],w[1][0]+v[3][0],4,4
};
break;
}case 2:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
w[0][0]+v[0][0],w[1][0]+v[2][0],I,I,
w[0][0]+v[1][0],w[1][0]+v[3][0],I,I,
w[2][0]+v[0][0],w[3][0]+v[2][0],I,I,
w[2][0]+v[1][0],w[3][0]+v[3][0],I,I,4,2
};
break;
}case 3:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
w[0][0]+v[0][0],I,w[1][0]+v[1][0],I,
I,w[0][0]+v[0][0],I,w[1][0]+v[1][0],
w[2][0]+v[0][0],I,w[3][0]+v[1][0],I,
I,w[2][0]+v[0][0],I,w[3][0]+v[1][0],4,4
};
break;
}
}break;
}case 4:{
switch(tg[u]){
case 1:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
w[0][0]+v[0][0],w[2][0]+v[0][0],I,I,
w[1][0]+v[1][0],w[3][0]+v[1][0],I,I,
I,I,I,I,I,I,I,I,2,2
};
break;
}case 2:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
w[0][0]+v[0][0],I,w[1][0]+v[0][0],I,
I,w[0][0]+v[1][0],I,w[1][0]+v[1][0],
I,I,I,I,I,I,I,I,2,4
};
break;
}case 3:{
auto &w=vl_son[u][0],&v=vl_son[u][1];
G={
std::max(w[0][0]+v[0][0],w[1][0]+v[2][0]),I,I,I,
I,std::max(w[0][0]+v[1][0],w[1][0]+v[3][0]),I,I,
I,I,I,I,I,I,I,I,2,2
};
break;
}
}break;
}
}
}
void pushup(int u){
prod[u]=g[u];
if(lc[u])prod[u]=prod[lc[u]]*prod[u];
if(rc[u])prod[u]=prod[u]*prod[rc[u]];
}
int subbuild(int l,int r){
if(l==r){calc_g(st[l]),pushup(st[l]);return st[l];}if(l>r)return 0;
int m=std::lower_bound(sm+l,sm+r+1,(sm[l]+sm[r])>>1)-sm;
int u=st[m];lc[u]=subbuild(l,m-1),rc[u]=subbuild(m+1,r);
fa[lc[u]]=fa[rc[u]]=u,calc_g(u),pushup(u);return u;
}
int build(int u){
for(int re p=u;p;p=son[p])
lsz[p]=sz[p]-sz[son[p]];
for(int re p=u;p;p=son[p]){int cso=0;
for(int re w=el[p];w;w=nx[w])if(!lsz[w]){
int v=build(w);tg_son[v]=cso;
fa[v]=p,vl_son[p][cso++]=prod[v];
}
}tp=0;for(int re p=u;p;p=son[p])
st[++tp]=p,sm[tp]=sm[tp-1]+lsz[p];
return subbuild(1,tp);
}
void work(){
rt=build(rt);int Q=gi();
print(std::max(prod[rt][0][0],prod[rt][1][0]),'\n');
while(Q--){
int u=gi(),v0=gi(),v1=gi();
E[u].v0=v0,E[u].v1=v1;calc_g(u);
while(u){
pushup(u);
if(fa[u]&&(lc[fa[u]]!=u&&rc[fa[u]]!=u))
vl_son[fa[u]][tg_son[u]]=prod[u],calc_g(fa[u]);
u=fa[u];
}print(std::max(prod[rt][0][0],prod[rt][1][0]),'\n');
}
}
}
namespace G{//Graph
int id[N],d[N],vs[N];
std::unordered_map<int,int> eid[N];
void init(){
for(int re i=1;i<=n;++i)id[i]=i;
for(int re i=1;i<=rt;++i)T::sz[i]=1;
for(int re i=1;i<=m;++i){
int u=E[i+n].u,v=E[i+n].v;
eid[u][v]=i+n,eid[v][u]=-i-n;
++d[u],++d[v];
}std::queue<int> q;
for(int i=1;i<=n;++i)
if(d[i]<=2)q.push(i),vs[i]=true;
while(!q.empty()){
int u=q.front();q.pop();
switch(d[u]){
case 1:{
auto t=eid[u].begin();int v=t->fi,e=t->se;
eid[u].clear();eid[v].erase(u);--d[v];
if(e>0)id[v]=T::node(4,id[u],e,id[v]);
else id[v]=T::node(4,id[u],T::node(2,-e),id[v]);
if(!vs[v]&&d[v]<=2)q.push(v),vs[v]=true;
break;
}
case 2:{
int w=u,v,eu,ev,e;
auto t=eid[w].begin();
u=t->fi,eu=t->se;++t;
v=t->fi,ev=t->se;eid[w].clear();
eid[u].erase(w),eid[v].erase(w);
if((ev>0)!=(eu<0)){
if(ev<0)ev=T::node(2,-ev);
else eu=-T::node(2,eu);
}if(eu>0)std::swap(u,v),std::swap(eu,ev);
e=T::node(3,-eu,id[w],ev);
if(eid[u][v]){
--d[u],--d[v];
int et=eid[u][v];
if(et<0)et=T::node(2,-et);
e=T::node(1,e,et);
}eid[u][v]=e,eid[v][u]=-e;
if(!vs[u]&&d[u]<=2)q.push(u),vs[u]=true;
if(!vs[v]&&d[v]<=2)q.push(v),vs[v]=true;
break;
}
}
}
}
}
void Main(){
n=gi(),m=gi();rt=n+m;
for(int re i=1;i<=n;++i){
int w=gi(),s=gi();
E[i]={0,0,w,s};
}for(int re i=1;i<=m;++i){
int u=gi(),v=gi(),c=gi(),d=gi();
E[i+n]={u,v,c,d};
}G::init();T::work();
}
inline void file(){
#ifdef zxyoi
freopen("park.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}