[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=add(ans,p[bl[u]].rhs);bl[v]=bl[u];if(u!=p[bl[u]].s)bl[u]=0;
	}
	else{
		bl[u]=bl[v]=++idx;p[bl[u]].siz=1;p[bl[u]].s=u;p[bl[u]].t=v;
		p[bl[u]].bhs=pow2[cnt];p[bl[u]].fir=p[bl[u]].til=cnt;
	}
	if(cnt>m)printf("%d\n",ans);
}
void sakura(){
	Ans.clear();while(!q.empty())q.pop();++tim;int anss=0; 
	for(int i=1;i<=idx;i++)if(p[i].siz>1)q.push(p[i].fir),dis[p[i].fir]=0,vis[p[i].fir]=tim;
	while(!q.empty()){
		int t=q.front();q.pop();if(dis[t]&1)Ans.push_back(t),anss=add(anss,pow2[t]);
		if(ch[t][0]&&vis[ch[t][0]]!=tim)q.push(ch[t][0]),vis[ch[t][0]]=tim,dis[ch[t][0]]=dis[t]+1;
		if(ch[t][1]&&vis[ch[t][1]]!=tim)q.push(ch[t][1]),vis[ch[t][1]]=tim,dis[ch[t][1]]=dis[t]+1;
	}
	printf("%d",(int)Ans.size());for(int i=0;i<(int)Ans.size();i++)printf(" %d",Ans[i]);puts("");
}
int main(){
	read(n1);read(n2);read(m);pow2[0]=1;
	for(int i=1,u,v;i<=m;i++)read(u),read(v),v+=n1,work(u,v);read(Q);
	for(int i=1;i<=Q;i++){int typ,u,v;read(typ);if(typ==1)read(u),read(v),v+=n1,work(u,v);else sakura();fflush(stdout);}
	return 0;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号