uva1459Flowers Placement(二分图+dfs)

<pre name="code" class="cpp">/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2016
File Name   :
给定n行m列的花的摆放方式,要求就是每行每列不出现同色的,求第k字典序的摆放方式。
思路:从第一行开始枚举放什么花色,然后就是判断是否和题目的要求,这里的判断方式就是
二分图的dfs部分同来进行摆放关系的调整,但是不能调整当前行前面的已经确定的花色,这
样得到的字典序不是严格从1到k递增的字典序。
还有就是G中的点是有序的。
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
#define lson rt << 1
#define rson rt << 1 | 1
#define bug cout << "BUG HERE\n"
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int nCase = 0;
const int maxn = 210;
vector<int> G[maxn], vec;
bool mp[maxn][maxn];
int linker[maxn];
int vis[maxn];
int used[maxn];
int n, m, k;
inline void Input() {
	scanf("%d%d%d",&n,&m,&k);
	int x;
	memset(mp, false,sizeof mp);

	for (int i = 1;i <= m;++i) {
		for (int j = 1;j <= n;++j) {
			scanf("%d",&x);
			mp[j][x] = true;
		}
	}

	//根据已有的花色进行建图。
	for (int i = 1;i <= n;++i) {
		G[i].clear();
		for (int j = 1;j <= n;++j)
			if (!mp[i][j]) G[i].push_back(j);
	}

	//show map
	// for (int i = 1;i <= n;++i) {
	// 	for (int j = 0;j < G[i].size();++j)
	// 		printf("%4d", G[i][j]);
	// 	puts("");
	// }
	// puts("***********************");
}
bool search(int u, int limit) {
	if (u <= limit) return false;

	for (int i = 0;i < G[u].size();++i) {
		int v = G[u][i];

		if (vis[v]) continue;
		vis[v] = true;

		if (linker[v] == -1 || search(linker[v], limit)) {
			linker[v] = u;
			return true;
		}
	}
	return false;
}
inline int Hungary() {
	int ret = 0;
	memset(linker, -1,sizeof linker);

	for (int i = 1;i <= n;++i) {
		memset(vis, 0,sizeof vis);
		if (search(i, 0)) ret++;
	}

	return ret;
}
int cnt;
int tmp[maxn];
inline bool check(int v, int u) {
	if (linker[v] == u) return true;

	int t = 1;
	for (int i = 1;i <= n;++i) {//T-Set
		vis[i] = false;
		tmp[i] = linker[i];
		if (linker[i] == u) t = i;
	}
	int nf = linker[v];//S-Set
	linker[v] = u;
	linker[t] = -1;

	if (search(nf, u)) return true;
	else {
		memcpy(linker, tmp, sizeof tmp);
		return false;
	}
	return false;
}


bool dfs(int u) {
	// cout << "u = " << u << endl;
	if (u == n + 1) return ++cnt == k;

	for (int i = 0;i < G[u].size();++i) {
		int v = G[u][i];
		if (used[v]) continue;
		if (check(v, u)) {
			used[v] = true;
			vec.push_back(v);
			if (dfs(u + 1)) return true;
			vec.pop_back();
			used[v] = false;
		}
	}
	return false;
}


inline void solve() {
	memset(used, 0,sizeof used);
	vec.clear();
	cnt = 0;
	int now;
	if ((now = Hungary()) == n && dfs(1)) {
		for (int i = 0;i < n;++i)
			printf(" %d", vec[i]);
		puts("");
	}else puts(" -1");
	// cout << now << endl;
}

int main(int argc, const char * argv[])
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--) {
		Input();
		printf("Case #%d:", ++nCase);
		solve();
	}
	return 0;
}


 

你可能感兴趣的:(DFS,二分图)