TopCoder SRM 682 Div1 Problem 450 SuccessfulMerger (环套树 + 分类讨论)

题意  给定一个$n$个点$n$条边的无向图,现在要把这个图进行若干次操作,并选择一个点作为首都。

   要求除首都外的任意两个点$u$, $v$,从$u$走到$v$必须经过这个首都。

操作为合并两个相邻的点为一个点,即把这两个点从原图中删除,连接这两个点的边接到新的点上去。

考虑最后这个图的形态其实是一个菊花图,那么可以考虑到最后剩下的这些点其实只有选出的首都和

原图中度数为$1$的点。

但是有这么一种比较特殊的情况。

这个图也是符合题意的。

原来的图其实是一个环套树(环的大小可能为$2$)

如果这个环上存在一个度数为$2$的点(即除了和环上的点相连之外其他没有点和他相连)

那么这个点也可以被留下,但是所有这样的点中最多只能留下一个。

于是答案就很显然了。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair

typedef long long LL;
typedef pair <int, int> PII;

const int N = 105;

int vis[N], father[N], isroot[N], a[N];
int cnt;
int flag;
int n, now, ans;
int xx, yy;
map <PII, int> mp;
vector <int> v[N];

int get_circle(int x){
	vis[x] = 1;
	for (auto u : v[x]){
		if (u == father[x]) continue;
		father[u] = x;
		if (vis[u]){
			cnt = 0;
			int w = x;
			while (w ^ u){
				a[++cnt] = w;
				isroot[w] = cnt;
				w = father[w];
			}

			a[++cnt] = u;
			isroot[u] = cnt;
			return 1;
		}

		if (get_circle(u)) return 1;
	}

	return 0;
}

void dfs(int x){
	vis[x] = 1;
	for (auto u : v[x]){
		if (vis[u] || isroot[u]) continue;
		dfs(u);
	}
}

class SuccessfulMerger{
	public:
		int minimumMergers(vector<int> road){
			memset(a, 0, sizeof a);
			memset(isroot, 0, sizeof isroot);
			memset(father, 0, sizeof father);
			memset(vis, 0, sizeof vis);
			cnt = 0;
			n = 0;
			flag = 0;
			mp.clear();
			rep(i, 0, 100) v[i].clear();
			for (auto u : road){
				++n;
				++u;
				int x = n, y = u;
				if (x > y) swap(x, y);
				if (mp.count(MP(x, y))){
					flag = 1;
					xx = x, yy = y;
					continue;
				}

				mp[MP(x, y)] = 1;
				v[x].push_back(y);
				v[y].push_back(x);
			}

			if (flag){
				cnt = 2;
				a[1] = xx;
				a[2] = yy;
			}

			else get_circle(1);

			if (flag){
				v[xx].push_back(yy);
				v[yy].push_back(xx);
			}

			ans = n - 1;
			rep(i, 1, n) if ((int)v[i].size() == 1) --ans;

			rep(i, 1, cnt){
				int ccc = 0;
				for (auto u : v[a[i]]){
					int fg = 0;
					rep(j, 1, cnt) if (u == a[j]) fg = 1;
					if (fg == 0) ccc = 1;
				}

				if (ccc == 0){ --ans; break; }
			}

			return ans;
		}
};

  

原文地址:https://www.cnblogs.com/cxhscst2/p/8449181.html

时间: 2024-08-03 17:39:19

TopCoder SRM 682 Div1 Problem 450 SuccessfulMerger (环套树 + 分类讨论)的相关文章

topcoder srm 682 div1 -3

1.给定一个$n$个节点的无向图.找到一个长度为4的链.$5\leq n \leq 2000$ 思路:枚举链的起点,暴力搜索即可.因为假设图中最长链的长度是3,那么搜索的最大复杂度是$O(n^{2})$. #include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <vector> #include <set> #inclu

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

Topcoder SRM 648 Div1 250

Problem 给一个长度为N的"AB"字符串S,S只含有两种字符'A' 或 'B',设pair(i,j)(0=<i<j<N)表示一对 i,j 使得S[i]='A',S[j]='B'.现给定一个K,求字符串S,使得pair(i,j)的个数恰好为K.若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [2, 50] K: [0 , N*(N-1)/2 ] Solution 若K>(N/2

Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

Problem Statement      The Happy Letter game is played as follows: At the beginning, several players enter the field. Each player has a lowercase English letter on their back. The game is played in turns. In each turn, you select two players with dif

POJ 2826 An Easy Problem?!(线段相交,分类讨论)

题意:给两个线段,问他们能收集到多少雨水. 链接:http://poj.org/problem?id=2826 解法:分四种情况讨论 1. 存在一个线段与x轴平行,答案为0 2. 两个线段没有交点,答案为0 3. 1和2都不满足时,令线段1为比较低的那个线段,且p1为其比较高的那个点,若该点往y轴正方向的射线与线段2有交点,则答案为0 4. 3不满足时,求出两线段交点x1,p1做一条平行于x轴的线,该线与线段2的交点x2,则三角形x1, x2, p1的面积就是答案 小结:此题属于分类讨论型的题,

topcoder srm 738 div1 FindThePerfectTriangle(枚举)

Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle with the following properties: The coordinates of each vertex are integers between 0 and 3000, inclusive. The perimeter of the triangle must be exactly

Topcoder SRM 653 Div1 250

Problem N个人坐成一排,属于同一个公司的人都坐在一起(挨在一起),但不知道谁属于哪个公司.现在问其中的某些人 他属于哪个公司,他的回答是Ai,Ai=0表示此人未被询问,否则表示他的回答.题目保证一定存在一种分组方案使得属于同一公司的人都坐在一起.现问方案是否唯一? Limits TimeLimit(ms):2000 MemoryLimit(MB):256 N,Ai∈[1,100] Solution 设dp[i]表示从i位置开始往后分组的情况,dp[i]=0表示无法分组,dp[i]=1表示

Topcoder SRM 547 Div1 250

Problem On a horizontal line, there are two vertical pillars. The distance between their bottoms is w. The height of the first pillar is an integer, chosen uniformly at random in the range 1 through x, inclusive. The height of the second pillar is an

Topcoder SRM 605 div1 题解

日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的个数)乘积越大,输出这个最大值.数据满足n<=50,type<=100,abs(taste)<=100000. 这题好像是个贪心,才不是呢啊哼- 首先我们发现,如果若干个汉堡包有同一个type值,那么我们可以把这一些汉堡包看成一个新的大汉堡包,它的type就是原来的type,它的taste就