• CF1610F F. Mashtali: a Space Oddysey


    我们首先发现有如下性质:
    我们不妨先随机定向边,那么我们发现无论我们如何翻转边。
    都会对其两端的点,造成 \(2 / 4\) 的影响,所以我们发现如果一个点其和他相连的所有边权和为偶数,则我们不能调整其为好点。

    那么我们自然的思考,是否能够构造一种方案使得所有边权和为奇数的都可以成为好点。

    我们下列先给出一个方案再进行一个证明。

    我们对所有的奇度点都与一个虚点相连一条边权为 \(1\) 的虚边。

    我们知道一条边会同时改变两点的度数奇偶情况,即奇度数点为偶数。

    所以我们操作之后一定所有点都是偶数,那这图是一个欧拉回路。

    考虑我们在进行欧拉回路的遍历时,我们首先满足让出边让入边的边权相等,否则使用另一边。

    考虑对边权为偶数的我们可以任意定向,那我们不进行考虑。

    那么我们考虑边权为奇数的,那么有两种情况。

    一:奇数条边权为 \(1\) 的边,奇数条的边权边权为 \(2\) 的边。

    此种情况,我们按我们的操作的一定会最后只会抵消到只剩一条边权为 \(1\) 的和一条边权为 \(2\) 的边。

    那么其为好点。

    一:奇数条边权为 \(1\) 的边,偶数条的边权边权为 \(2\) 的边。

    此种情况,我们按我们的操作的一定会最后只会抵消到只剩一条边权为 \(1\)

    那么其为好点。

    所以我们只要按照这种操作即可使得所有边权和的奇数的点都是好点。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<list>
    #define ll lonng long
    #define N 600005
    
    bool begin;
    
    int n,m;
    
    int to[N];
    int from[N];
    
    int sum[N];
    
    int fans,ans[N];
    
    int vis[N];
    
    int cnt[N];
    
    std::vector<int>Q[N][3];//边权为1,边权为2
    int head[N][3];
    
    int dfn[N];
    
    bool end;
    
    inline void dfs(int u,int now){
    //	std::cout<<u<<" "<<now<<std::endl;
    //	std::cout<<"rest"<<head[u][now]<<" "<<head[u][3 - now]<<std::endl;
    	int fnow = now;
    	while(!(Q[u][now].size() <= head[u][now] && Q[u][3 - now].size() <= head[u][3 - now])){
    	dfn[u] = 1;
    	while(head[u][now] < Q[u][now].size() && vis[Q[u][now][head[u][now]]])
    	head[u][now] ++;	
    	while(head[u][3 - now] < Q[u][3 - now].size() && vis[Q[u][3 - now][head[u][3 - now]]])
    	head[u][3 - now] ++;	
    	if(Q[u][now].size() != head[u][now]){
    		ans[Q[u][now][head[u][now]]] = (u == from[Q[u][now][head[u][now]]]) + 1;
    		vis[Q[u][now][head[u][now]]] = 1;
    //		std::cout<<"("<<u<<"->"<<" "<<(to[Q[u][now][head[u][now]]] - u)<<")"<<std::endl;
    //		std::cout<<Q[u][now].front()<<std::endl;
    		dfs(to[Q[u][now][head[u][now]]] - u,now);
    		head[u][now] ++ ;
    	}else{
    		now = 3 - now;
    		if(Q[u][now].size() != head[u][now]){
    		ans[Q[u][now][head[u][now]]] = (u == from[Q[u][now][head[u][now]]]) + 1;
    		vis[Q[u][now][head[u][now]]] = 1;
    //		std::cout<<"("<<u<<"->"<<" "<<(to[Q[u][now][head[u][now]]] - u)<<")"<<std::endl;		
    //		std::cout<<Q[u][now].front()<<std::endl;
    		dfs(to[Q[u][now][head[u][now]]] - u,now);
    		head[u][now] ++ ;
    	}	
    	}
    	now = fnow;
    	}
    	return ;
    }
    
    int main(){
    //	std::cout<<(&end - &begin) / 1024 / 1024<<std::endl;
    	scanf("%d%d",&n,&m);
    	for(int i = 1;i <= m;++i){
    		int x,y,p;
    		scanf("%d%d%d",&x,&y,&p);
    		to[i] = x + y;
    		cnt[x] ++ ;
    		cnt[y] ++ ;
    		from[i] = x;
    		sum[x] += p;
    		sum[y] += p;
    		Q[x][p].push_back(i);
    		Q[y][p].push_back(i);
    	}
    	int mcnt = m;
    	for(int i = 1;i <= n;++i){
    		if(sum[i] & 1)
    		fans ++ ;
    		if(cnt[i] & 1){
    			int x = n + 1;
    			int y = i;
    			int p = 1;
    			to[++mcnt] = x + y;
    			from[mcnt] = x;
    			Q[x][p].push_back(mcnt);
    			Q[y][p].push_back(mcnt);
    		}
    	}
    	for(int i = 1;i <= n + 1;++i)
    	if(!dfn[i])
    	dfs(i,1);
    	std::cout<<fans<<std::endl;
    	for(int i = 1;i <= m;++i)
    	std::cout<<(ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    不得不爱开源 Wijmo jQuery 插件集(6)【Popup】(附页面展示和源码)
    遗漏的知识点
    初识函数
    ==和is的区别 以及编码和解码
    函数的动态参数 及函数嵌套
    基本数据类型补充、set集合、深浅拷贝
    文件操作
    基本数据类型之“字典”
    建立自己的Servlet
    还原误删数据笔记
  • 原文地址:https://www.cnblogs.com/dixiao/p/15607635.html
Copyright © 2020-2023  润新知