[CF1499G]Graph Coloring
Posted Tan_tan_tann
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1499G]Graph Coloring相关的知识,希望对你有一定的参考价值。
Graph Coloring
题解
一个晚上又没了。。。
我们考虑什么情况下
∑
v
∈
V
∣
r
(
v
)
−
b
(
v
)
∣
\\sum_{v\\in V}\\left|r(v)-b(v)\\right|
∑v∈V∣r(v)−b(v)∣最小。
很明显,这个值不可能小于
∑
v
∈
V
∣
d
e
g
v
%
2
∣
\\sum_{v\\in V}|deg_{v}\\%2|
∑v∈V∣degv%2∣,因为度数为奇数的点
∣
r
(
v
)
−
b
(
v
)
∣
|r(v)-b(v)|
∣r(v)−b(v)∣最少为
1
1
1,它不可能让
r
(
v
)
=
b
(
v
)
r(v)=b(v)
r(v)=b(v)。
我们考虑如何让这个值刚好达到
d
e
g
deg
deg为奇数的点的个数。
我们可以尝试在这个图上构造路径,在路径上,我们对边交替染色,这样路径上非端点的点不会产生贡献,而端点会产生
1
1
1的贡献。
而必定存在一种染色方法使得所有
d
e
g
deg
deg为奇数的点为一条路径的端点,而偶数的点不为任何路径的端点。
因为如果对于偶数的点,它为端点的路径数一定是偶数,我们可以将经过它的端点们互相合并,最后它就没有路径出发了。而为奇数的点无论怎么消都会剩余一条路径,产生
1
1
1的贡献。
这样的话就刚好可以使图的权值最小。
但题目会动态加边并询问,我们必须要动态维护路径及其
h
a
s
h
hash
hash值。
由于一个点最多作为一条路径的端点,我们没必要理会经过它的路径,只考虑它作端点的路径。当我们加入边
(
u
,
v
)
(u,v)
(u,v)时,有
3
3
3种情况:
- 点 u , v u,v u,v都有路径出发,那么我们要加一条边,再将两条路径合并起来。
- 点 u u u或点 v v v有一个有路径出发,那我们相当于对一条路径进行增广。
- 点 u u u与点 v v v都不作端点,那我们相当于新加入一条路径。
而对于路径我们要维护其上的蓝色边
h
a
s
h
hash
hash和,红色边
h
a
s
h
hash
hash和,它的起终点与它的起终边。
由于合并路径时涉及到路径颜色的问题,相邻两条边需异色,如果合并的两条路径颜色相同我们可以直接将其合并,如果不同我们还要先将不同颜色的边交换后再合并。
考虑到合并的方便,我们可以先调整一下经过
u
u
u的路径的方向与经过
v
v
v的路径的方向。
但对于
t
y
p
e
=
2
type=2
type=2的询问,我们可以考虑先对于每条边记录下来它旁边的两条边,这同样可以再合并与增广时维护,再从一条路径的头开始,
b
f
s
/
d
f
s
bfs/dfs
bfs/dfs找出所有的红边。
为了减少输出,我们可以将路径上偶数的边赋为蓝边
t
y
p
e
=
2
type=2
type=2的询问不会超过
10
10
10次呀,那没事了。
虽然每个操作
1
1
1都是
O
(
1
)
O\\left(1\\right)
O(1),但常数巨大无比。
当然,时间复杂度还是
O
(
n
+
m
+
q
)
O\\left(n+m+q\\right)
O(n+m+q)的。
记得这是交互题哟!!!
源码
贞难调
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x7f7f7f7f7f7f7f7f;
const int mo=998244353;
const int jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
int n1,n2,m,cnt,bl[MAXN],ans,pow2[MAXN],idx,Q,ch[MAXN][2],tim,vis[MAXN],dis[MAXN];
struct path{int s,t,rhs,bhs,siz,fir,til;}p[MAXN];
vector<int>Ans;queue<int>q;
void work(int u,int v){
cnt++;pow2[cnt]=add(pow2[cnt-1],pow2[cnt-1]);
if(bl[u]&&bl[v]&&bl[u]!=bl[v]){
ans=add(ans,mo-add(p[bl[u]].rhs,p[bl[v]].rhs));
if(p[bl[u]].s==u){swap(p[bl[u]].s,p[bl[u]].t);swap(p[bl[u]].fir,p[bl[u]].til);if(p[bl[u]].siz+1&1)swap(p[bl[u]].rhs,p[bl[u]].bhs);}
if(p[bl[v]].t==v){swap(p[bl[v]].s,p[bl[v]].t);swap(p[bl[v]].fir,p[bl[v]].til);if(p[bl[v]].siz+1&1)swap(p[bl[v]].rhs,p[bl[v]].bhs);}
if(p[bl[u]].siz&1)p[bl[u]].rhs=add(p[bl[u]].rhs,add(pow2[cnt],p[bl[v]].rhs)),p[bl[u]].bhs=add(p[bl[u]].bhs,p[bl[v]].bhs);
else p[bl[u]].bhs=add(p[bl[u]].bhs,add(pow2[cnt],p[bl[v]].rhs)),p[bl[u]].rhs=add(p[bl[u]].rhs,p[bl[v]].bhs);
ch[cnt][0]=p[bl[u]].til;ch[cnt][1]=p[bl[v]].fir;ch[p[bl[u]].til][ch[p[bl[u]].til][0]?1:0]=ch[p[bl[v]].fir][ch[p[bl[v]].fir][0]?1:0]=cnt;
p[bl[u]].til=p[bl[v]].til;p[bl[u]].t=p[bl[v]].t,p[bl[u]].siz+=p[bl[v]].siz+1;p[bl[v]].siz=0;bl[p[bl[v]].t]=bl[u];
ans=add(ans,p[bl[u]].rhs);if(v!=p[bl[u]].t)bl[v]=0;if(u!=p[bl[u]].s)bl[u]=0;
}
else if(bl[u]||bl[v]){
if(bl[v])swap(u,v);ans=add(ans,mo-p[bl[u]].rhs);
if(p[bl[u]].s==u){swap(p[bl[u]].s,p[bl[u]].t);swap(p[bl[u]].fir,p[bl[u]].til);if(p[bl[u]].siz+1&1)swap(p[bl[u]].rhs,p[bl[u]].bhs);}
if(p[bl[u]].siz&1)p[bl[u]].rhs=add(p[bl[u]].rhs,pow2[cnt]);
else p[bl[u]].bhs=add(p[bl[u]].bhs,pow2[cnt]);
ch[p[bl[u]].til][ch[p[bl[u]].til][0]?1:0]=cnt;ch[cnt][0]=p[bl[u]].til;p[bl[u]].til=cnt;
p[bl[u]].t=v;p[bl[u]].siz++;ans=addCF662B Graph Coloring题解--zhengjun
CF1354E Graph Coloring (二分图+dp)