題目鏈接:點擊打開鏈接
題目大意:給你一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;
}