ural 1208. Legendary Teams Contest 递归

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1208


题意描述:给定K支队伍,每队三个队员,不同队伍之间队员可能部分重复,输出这些队员同时能够组成多少完整的队伍;


思路大致是就是用递归去穷举每支队伍;


AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;

struct Team{
	int value;
	int degree;
	vector<int>mem;
	Team() :value(0), degree(3){}
};
vector<Team>team;

//vector<int>team;

vector<vector<int> >v;
vector<bool> ava;
map<string, int>m;
int k, ans, lim;

inline void m_add(string &s, int t){
	if (m.find(s) == m.end())
		m[s] = ans++;
	v[m[s]].push_back(t);
	team[t].mem.push_back(m[s]);
}

void init(){
	cin >> k;
	team.resize(k);
	v.resize(k * 3);

	lim = ans = 0;
	string sa, sb, sc;
	for (int i = 0; i < k; i++){
		cin >> sa >> sb >> sc;
		m_add(sa, i);
		m_add(sb, i);
		m_add(sc, i);
	}

	ava.resize(v.size(), true);

}

int get_One(int i){
	for ( ; i < team.size();i++)
	if (team[i].degree == 3)return i;

	return -1;
}

void make_one(int index){
	for (int i = 0; i < 3; i++){
		int k = team[index].mem[i];
		ava[k] = false;
		for (int j = 0; j < v[k].size(); j++)
			team[v[k][j]].degree--;
	}
}

void release_one(int index){
	for (int i = 0; i < 3; i++){
		int k = team[index].mem[i];
		ava[k] = true;
		for (int j = 0; j < v[k].size(); j++)
			team[v[k][j]].degree++;
	}
}

void recur(int pre, int depth){

	ans = ans>depth ? ans : depth;

	if (ans == lim)return;

	int res = get_One(pre);
	if (res == -1)return;

	make_one(res);
	recur(res + 1, depth + 1);
	release_one(res);
	recur(res + 1, depth);

}

void func(){
	
	init();
	
	for (int i = 0; i < ans; i++)
		lim = v[i].size()>lim ? v[i].size() : lim;
	lim = ans - lim + 1;
	ans = 0;

	recur(0, 0);

	cout << ans << endl;

}

int main(){

	//freopen("out.txt", "w", stdout);
	//freopen("in.txt", "r", stdin);

	func();

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值