题意:给你n个环,这些环有一些已经连在了一起,你可以将其中的一些环打开在关闭,问你最少打开几个环可以使所有的环联成一条链。
思路:这个题比赛的时候用并查集加欧拉路写的,但是并没有写出来,比赛结束了以后我看了一下题解,发现因为圆环的个数最多只有十五个,所以这个题目可以用二进制来枚举所有的子集来做,找到所需要最少的环。
有几个要注意的地方:
1.如果断开环以后,还有分支数大于2的无法构成一条链
2.如果断开环以后,还能成回路无法连成一条链
3.断开以后所有剩余的部分大于断开的环数加一无法连成一条链
PS;一开始自己判断有多少个散落的的环的方法是用的并查集十分的麻烦,后来看到别的方法更加的简单。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <list>
#define MAXN 20
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define pi acos(-1.0)
using namespace std;
bool lin[MAXN][MAXN];
bool temp[MAXN][MAXN];
int vis[MAXN];
int visit[MAXN];
int ans;
bool F;
int n;
void dfs(int x, int start) {
for (int i = 0; i < n; ++i) {
if (temp[x][i] && i != start) {
visit[i]++;
if (visit[i] < 2)
dfs(i, x);
}
}
}
void solve(int s) {
int cnt = 0;
memcpy(temp, lin, sizeof(lin));
for (int i = 0; i < n; ++i) {
if (s & (1 << i)) {
cnt++;
for (int j = 0; j < n; ++j) {
temp[i][j] = false;
temp[j][i] = false;
}
}
}
bool flag = true;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (temp[i][j]) {
vis[i]++;
}
}
}
int node = 0;
memset(visit, 0, sizeof(visit));
for (int i = 0; i < n; ++i) {
if (!(s & (1 << i)) && !visit[i]) {
visit[i]++;
dfs(i, -1);
node++;
}
}
for (int i = 0; i < n; ++i) {
if (vis[i] > 2) {
flag = false;
break;
}
if (visit[i] >= 2) {
flag = false;
break;
}
}
if (node > cnt + 1)
flag = false;
if (flag)
ans = min(ans, cnt);
}
int main() {
std::ios::sync_with_stdio(false);
int x, y;
int kase = 0;
while (cin >> n && n) {
memset(lin, false, sizeof(lin));
while (cin >> x >> y) {
if (x == -1 && y == -1)
break;
lin[x - 1][y - 1] = true;
lin[y - 1][x - 1] = true;
}
ans = INF;
for (int i = 0; i < (1 << n); ++i) {
solve(i);
}
cout << "Set " << ++kase << ": Minimum links to open is ";
cout << ans << endl;
}
return 0;
}
/*
5 1 2 2 3 4 5 -1 -1
7 1 2 2 3 3 1 4 5 5 6 6 7 7 4 -1 -1
4 1 2 1 3 1 4 -1 -1
3 1 2 2 3 3 1 -1 -1
3 1 2 2 1 -1 -1
0
*/