2016 Multi-University Training Contest 1 1005 Necklace

題目鏈接:點擊打開鏈接

題目大意:給你一2*n個珠子,n個陽珠子,n個陰珠子,另外有m中情況,當a號陽珠子和b號陰珠子在一起的時候會變暗,求變暗的最小數量。

解題思路:(官方題解先放一邊,估計函數什麼的我真不太懂)做法就是全排列一種珠子的情況,然後嘗試着儘可能的放入陽珠子,找出最多能放多少就好。

重點在dfs的設計,這種設計我也是第一次看見,不得不說腦洞好大,當你找到一個位置的時候,它是合法位置的要求是:他左邊沒有點(或者右邊因爲是環,所以定好一個方向即可)或者是它左邊的點可以找到一個合適的新位置。

代碼:

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
using namespace std;
bool change[15][15],G[15][15];
int n, m, a[15];
int edge[15], vis[15];
bool dfs(int u)
{
	for (int v = 1;v <= n;v++)
	{
		if (vis[v] == 0 && G[u][v])
		{
			vis[v] = 1;
			if (edge[v] == -1 || dfs(edge[v]))
			{
				edge[v] = u;
				return true;
			}
		}
	}
	return false;
}
int solve()
{
	int ans = 0;
	memset(edge, -1, sizeof(edge));
	for (int i = 1;i <= n;i++)
	{
		memset(vis, 0, sizeof(vis));
		if (dfs(i))
			ans++;
	}
	return ans;
}
int main()
{
	while (scanf("%d %d", &n, &m) != EOF)
	{
		memset(change, true, sizeof(change));
		for (int i = 0;i < m;i++)
		{
			int x, y;
			scanf("%d %d", &x, &y);
			change[x][y] = false;
		}
		if (n == 0)
		{
			puts("0");
			continue;
		}
		if (n == 1)
		{
			if (change[1][1])
				puts("0");
			else
				puts("1");
			continue;
		}
		for (int i = 1;i <= n;i++)
			a[i] = i;
		int ans = -1;
		do {
			memset(G, false, sizeof(G));
			for (int i = 1;i <= n;i++)
			{
				for (int j = 1;j <= n;j++)
				{
					int next = j == n ? 1 : j + 1;
					if (change[i][a[j]] && change[i][a[next]])
						G[i][j] = true;
				}
			}
			ans = max(ans, solve());
		} while (next_permutation(a + 2, a + n + 1));
		printf("%d\n", n - ans);
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章