比较好的一道题目,首先建立一个2n个点的图,如果i和j题目类似,则在顶点i和顶点j直接连一条边。则问题转换为对顶点进行2-着色,使得红颜色的顶点数和蓝颜色的顶点数都为n。
首先求出整个图的连通分量,很明显必须每个连通分量都要能够进行朴素的2-着色,这个过程可以通过随便指定一个顶点的颜色,然后进行dfs确定其它顶点的颜色,如果该连同分量不能进行2-着色(比如存在偶环),那么很明显整个问题无解。
在对连同分量进行dfs的过程中,我们记录每个连同分量红色和蓝色的顶点的使用情况(要记录蓝色顶点有哪些,红色顶点有哪些),由于红色和蓝色是对称的!即红色换成蓝色,蓝色换成红色不影响着色,而我们最终的目的要使红色的顶点数和蓝色的顶点数都为n,这就构成一个dp过程!
设有c个连同分量,S1,S2,S3...,Sc,
连同分量Si进行2-着色使用的2中颜色的顶点数分别为Si[1]和Si[2]
ok[i][j]=true表示用对前i个连同分量进行着色颜色1使用的顶点个数为j这种情况可以发生
则有一下dp过程
ok[i][j]={ true, ok[i-1][j-Si[1]]=true or ok[i-1][j-Si[2]]=true
{ false, else
最后如果ok[c][n]=true的话,说明有解,否则误解。
注意到ok[i][...]只与ok[i-1][...]有关,这样可以用一个滚动数组,在每求出一个连同分量的时候进行一次dp状态转移就可以了。
要输出具体方案的话很简单,只需在dp过程中加如一个集合操作即可!