解题报告:洛谷 P3496 [POI2010]GIL-Guilds

题目描述

给一张无向图,要求你用黑白灰给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻;对于任意一个白点,至少有一个黑点与他相邻,对于任意一个灰点,至少同时有一个黑点和白点和灰点与他相邻,问能否成功

输入输出格式

输入格式:

第一行两个整数N(<=200000)和M(<=500000),分别指小镇个数和道路条数。

The towns are numbered from 1 to n.

Then the roads are given as follows: the input line no. i+1 describes the i-th road;

输出格式:

第一行:TAK (波兰语“是的”) - if the offices can be placed in towns according to these rules, or NIE (波兰语“不是”) - in the opposite case.

If the answers is TAK, then the following nlines should give an exemplary placement of the offices. Thus the line no. i+1 should hold:

the letter K if there should be an office of The Tailors Guild in the town i, or the letter S if there should be an office of The Sewers Guild in the town i, or the letter N if there should be no office in the town i.


代码

#include 
using namespace std;

const int MAXN = 200005,MAXM = 500005;

int n,m,e,ui,vi;
int head[MAXN],outs[MAXN],col[MAXN],vis[MAXN];
queue<int> Q;

struct edge
{
	int to,nxt;
}info[MAXM << 1];

inline void addedge(int from,int to)
{
	info[++e].to = to;
	info[e].nxt = head[from];
	head[from] = e;
}

void init()
{
	scanf("%d%d",&n,&m);
	for (int i = 1;i <= m;i++)
	{
		qread(ui);
		qread(vi);//快读
		addedge(ui,vi);
		addedge(vi,ui);
		outs[ui]++;
		outs[vi]++;
	}
}

void bfs(int S)
{
	Q.push(S);
	vis[S] = true;
	col[S] = 1;
	while (!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		for (int i = head[u];i;i = info[i].nxt)
		{
			int v = info[i].to;
			if (vis[v]) continue;
			vis[v] = true;
			col[v] = !col[u];
		}
	}
}

void work()
{
	for (int i = 1;i <= n;i++)
	{
		if (!outs[i])
		{
			puts("NIE");
			exit(0);
		}
	}
	puts("TAK");
	for (int i = 1;i <= n;i++)
	{
		if (vis[i]) continue;
		bfs(i);
	}
	for (int i = 1;i <= n;i++)
	{
		if (col[i]) puts("S");
		else puts("K");
	}
}

int main()
{
	init();
	work();
	return 0;
}

分析

  • 其实,发现染灰色点很不划算——因为它的要求更多。所以这题不染灰色点!

  • 题干中的“相邻”一词提醒我们,若一个点没有出度,即没有与他相邻的点,那么这种情况一定是不成立的,此时直接输出“NIE”。我们用outs数组维护出度数量。

  • 剩下的情况,只需要用一次BFS进行染色,当前节点的后继节点的颜色只需要和当前节点不同就可以了。

  • 不过本题的数据中存在图不联通的情况。为之奈何?作者本来打算建立超级源点,但是考虑到超级源点的颜色不好把握,而且到底谁和超级源点相连呢?

    于是联想到这一题的处理方式,考虑开一个vis数组,用于BFS时标记访问。一次BFS可以标记一个联通图,那么,不在同一联通图中的点就未被标记,在外层枚举BFS起点时加一个判断即可。

你可能感兴趣的:(解题报告)