生活随笔
收集整理的這篇文章主要介紹了
Cutting Chains UVA - 818
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目傳送門
題意:給你n個(gè)環(huán),這些環(huán)有一些已經(jīng)連在了一起,你可以將其中的一些環(huán)打開在關(guān)閉,問你最少打開幾個(gè)環(huán)可以使所有的環(huán)聯(lián)成一條鏈。
思路:這個(gè)題比賽的時(shí)候用并查集加歐拉路寫的,但是并沒有寫出來,比賽結(jié)束了以后我看了一下題解,發(fā)現(xiàn)因?yàn)閳A環(huán)的個(gè)數(shù)最多只有十五個(gè),所以這個(gè)題目可以用二進(jìn)制來枚舉所有的子集來做,找到所需要最少的環(huán)。
有幾個(gè)要注意的地方:
1.如果斷開環(huán)以后,還有分支數(shù)大于2的無法構(gòu)成一條鏈
2.如果斷開環(huán)以后,還能成回路無法連成一條鏈
3.斷開以后所有剩余的部分大于斷開的環(huán)數(shù)加一無法連成一條鏈
PS;一開始自己判斷有多少個(gè)散落的的環(huán)的方法是用的并查集十分的麻煩,后來看到別的方法更加的簡單。
#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;
}
總結(jié)
以上是生活随笔為你收集整理的Cutting Chains UVA - 818的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。