COCI 2018/2019 Round1 Teoretičar

Little Alan was bored so he asked Goran to give him an interesting problem. Since he’s busy with
preparing for exams, Goran could only recall one huge bipartite graph from his old days as a
programming competitor. He gave the graph to Alan and said: ​You have to colour the edges of this
bipartite graph using as few colours as possible in such a way that there are no two edges of the
same colour sharing a node.
Alan excitedly ran to his room, took out his movable read/write device for its tape and start to work on
the problem. However, he soon realized that he’s missing something so he got back to Goran and
said: ​Give me an infinite tape and I will solve your problem! Goran gave him a significant look: ​Infinite
tape? If you continue to theorize about everything, there won’t be a single thing named after you.
After seeing Alan starting to tear up, Goran decided to show mercy: ​I will make it a bit easier for you.
Let C be the smallest number of colours needed to paint the graph in the described way. I will let you
use at most X colours, where X is the lowest power of 2 not less than C.
Help Alan solve the problem.
Note ​: A bipartite graph is a graph whose nodes can be divided in two sets (or sides) in such a way
that each edge of graph connects one node from the first set with one node from the second set.

題意:一個二分圖,給邊染色使得共點的邊不同色,且用的顏色數量小於等於2k,其中k是最小的k滿足2k>=最小的滿足條件的顏色數,求染色方案。
點數n<=200000,邊數m<=500000
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
這個。乍一看可以亂搞,但是。。。。
首先可以想到一次給兩種顏色,一直給直到結束,然後,它WA了。
可以猜到最小顏色數爲最大點度數,但是直接染是O(n^2)的。
考慮把這些邊分爲兩個部分,使得每個點的度數都儘量被這兩個部分平分。
然後遞歸處理。
邊的分割用歐拉回路(適當加虛點和虛邊使得每個點的度數都爲偶數)
每次看外國網友的代碼都覺得他們太依賴STL了(還有就是代碼又長又醜又易懂)。
所以經常打CF會得STL依賴症?

AC Code:

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 1000005
using namespace std;

int m,n,l,r;
struct node{ int u,v; };
vector<node>edge,G;
vector<int>g[maxn];
int vis[maxm],tim,col[maxm],in[maxn];
int cl=0;

void dfs(int now)
{
	for(;g[now].size();)
	{
		int v = g[now].back();
		g[now].pop_back();
		if(vis[v]==tim) continue;
		col[v] = (cl^=1);
		vis[v] = tim;
		dfs(G[v].u == now ? G[v].v : G[v].u);
	}
}

vector<int>solve(vector<node>e)
{
	if(!e.size())
	{
		return {};
	}
	++tim;
	G=e;
	int cnt_e = e.size() , siz = cnt_e;
	vector<int>pt;
	for(int i=0;i<cnt_e;i++)
	{
		if(vis[e[i].u]!=tim) vis[e[i].u]=tim,g[e[i].u].clear(),in[e[i].u]=0,pt.push_back(e[i].u);
		if(vis[e[i].v]!=tim) vis[e[i].v]=tim,g[e[i].v].clear(),in[e[i].v]=0,pt.push_back(e[i].v);
		in[e[i].u]++,in[e[i].v]++;
		g[e[i].u].push_back(i);
		g[e[i].v].push_back(i);
	} 
	bool flag=0;
	for(vector<int>::iterator it = pt.begin();it!=pt.end();it++)
		flag |= g[*it].size() > 1;
	if(!flag)
	{
		vector<int>ret;
		for(int i=0;i<siz;i++) ret.push_back(1);
		return ret; 
	}
	in[n+1] = 0;
	for(vector<int>::iterator it = pt.begin();it!=pt.end();it++)
		if(in[(*it)] & 1) 
			if((*it)<=l)
			{
				g[n+2].push_back(cnt_e),
				in[n+2]++;
				g[*it].push_back(cnt_e++),
				G.push_back(node{*it,n+2});
			}
			else
			{
				g[n+1].push_back(cnt_e),in[n+1]++,
				g[*it].push_back(cnt_e++);
				G.push_back(node{n+1,*it});
			}
	if(in[n+1] & 1) 
		g[n+2].push_back(cnt_e),
		g[n+1].push_back(cnt_e++),
		G.push_back(node{n+1,n+2});
	++tim;
	for(vector<int>::iterator it = pt.begin();it!=pt.end();it++)
		dfs(*it);
	vector<node>tx,ty;
	vector<int>ccl;
	for(int i=0;i<siz;i++)
	{
		if(col[i]) ty.push_back(e[i]);
		else tx.push_back(e[i]);
		ccl.push_back(col[i]);
	}
	vector<int>rx=solve(tx),ry=solve(ty);
	int hx = *max_element(rx.begin(),rx.end()) , px=0,py=0;
	vector<int>ret;
	for(int i=0;i<siz;i++)
		if(ccl[i]) ret.push_back(ry[py++] + hx);
		else ret.push_back(rx[px++]);
	return ret;
}

int main()
{
	scanf("%d%d%d",&l,&r,&m),n=l+r;
	for(int i=1,u,v;i<=m;i++)
		scanf("%d%d",&u,&v),
		edge.push_back(node{u,v+l});
	vector<int>ans = solve(edge);
	printf("%d\n",*max_element(ans.begin(),ans.end()));
	for(int i=0;i<m;i++)
		printf("%d\n",ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章