您的位置:首页 > 产品设计 > UI/UE

ural 1742. Team building

2015-08-27 22:29 513 查看
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1742

题意描述:一家公司,每个程序员都有自己唯一崇拜的大神(next);公司主管想用一个算法将这些程序员分成若干项目组,算法描述如下:

1.从剩下未分配的程序员中随机选出一个,标记为current程序员;

2.新建一个项目,将current分配进该项目;

3.若current有崇拜的大神,并且那个大神还没被分配,将大神分配进current所属项目组,并将大神变为current,重复3;否则回到1;

求按照这个算法所需的项目组数量的最大值和最小值;

思路大致是:入度为0的遍历 + 完全独立环的个数 = min; 节点数n - 形成环的节点个数 + 环数 = max;

代码中有几点细节需要说明:

1.step表示遍历节点的顺序,可在遍历判断出环时(遇到本轮遍历过的节点即可判断是环)用当前step-节点中的step得到环长度;

2.circle变量用于储存是在哪轮遍历中首次被遍历的点,用于对1的思路剪枝;

3.代码分成两个过程:遍历入度为0的点顺便找一下其中的环,遍历独立环;

AC代码:

//#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

struct Node{
bool visit;
int in, next, step, circle;
Node() :circle(-1), visit(false), in(0), next(-1){}
};

void func(){

int n, single, bCircle, cCircle, cnt, step;
scanf("%d", &n);
vector<Node>v(n + 1);

for (int i = 1; i <= n; i++){
scanf("%d", &v[i].next);
v[v[i].next].in++;
}

single = bCircle = cCircle = cnt = step = 0;

for (int i = 1; i <= n; i++){
if (v[i].in == 0 && v[i].visit == false){
single++;
int src = i;
while (true){
v[src].step = step++;
v[src].visit = true;
v[src].circle = i;

src = v[src].next;
if (src == -1)break;
v[src].in--;

if (v[src].visit == false)continue;
else if (v[src].circle == i){
cnt += step - v[src].step;
bCircle++;
}
break;
}
}
}

for (int i = 1; i <= n; i++){
if (v[i].visit == false){
int src = i; cCircle++;
while (true){
v[src].visit = true;
v[src].step = step++;

src = v[src].next;
if (v[src].visit){
cnt += step - v[src].step;
break;
}
}
}
}

printf("%d %d\n", single + cCircle, n - cnt + bCircle + cCircle);

}

int main(){

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

func();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: