初看这个题目就是个简单无向图的2-着色问题,但是本题有个特殊的要求,既用到的两种颜色的顶点数目要一样!

比较好的一道题目,首先建立一个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过程中加如一个集合操作即可!

ural 1156#include <iostream>
ural 1156#include 
<cstdlib>
ural 1156#include 
<set>
ural 1156
using namespace std;
ural 1156
ural 1156
const int maxn=50;
ural 1156
bool g[maxn*2+1][maxn*2+1];
ural 1156
int l[maxn*2+1],c[3];
ural 1156
bool ok[maxn+1],newok[maxn+1];
ural 1156
set<int> s[3];
ural 1156
set<int> way[maxn+1],newway[maxn+1];
ural 1156
int n,m;
ural 1156
}


相关文章: