2015-2016 ACM-ICPC Southwestern Europe Regional Contest (SWERC 15) A题Promotions

64 篇文章 0 订阅
25 篇文章 4 订阅

题目大意:给你一个DAG关于1(E-1)个数字,然后有一个[A,B]的区间,让你给其中一些人升职,但是升职的前提是需要给他的上级升职,也就是说1->2意味着当你要给2升职的之前,先让他的上级1升职,然后问的是,要想让A个人升职时肯定要升职的人数是多少,让B个人升职肯定升职的人数,然后再输出给即使给B个人升职,也升职不到的人数有几个

 

 

解题思路:要想算出肯定升值的人,肯定要找出来有多少人在升职之前需要先升职某个人,need[i]指的是升职之前需要先升职i的人人数,need[i]越大意味着他率先升职的位次越靠后,根据need就可以求出来,一个人升职之前不需要升职的人有多少个,称之为noneed[i],我们就可以根据noneed[i]越小意味着升职位置越靠前

对于求出谁肯定不升职来说就很简单了,判断一下该人升职前所需要升职的人数与B的关系即可

#include<iostream>    
#include<cstdio>  
#include<stdio.h>  
#include<cstring>    
#include<cstdio>    
#include<climits>    
#include<cmath>   
#include<vector>  
#include <bitset>  
#include<algorithm>    
#include <queue>  
#include<map>  
using namespace std;

vector<int> b[5005], a[5005];
queue<int> qua;
bool needs[5005][5005];
int noneed[5005], need[5005], flag[5005];
int A, B, E, P, j, k, ans, l, r, ss;
void dfs(int x, int y)
{
	for (int i = 0; i < b[x].size(); i++)
	{
		if (b[b[x][i]].size() != 0 && flag[b[x][i]] == 0)
		{
			flag[b[x][i]] = 1;
			dfs(b[x][i], y);
		}
		needs[y][b[x][i]] = true;
	}
}
int main()
{
	int x, y, i;
	cin >> A >> B >> E >> P;
	memset(needs, false, sizeof(needs));//needs[i][j]表示j是i的上级,i升职前需要先升职j
	memset(noneed, 0, sizeof(noneed));
	memset(need, 0, sizeof(need));
	for (i = 1; i <= P; i++)
	{
		cin >> x >> y;
		b[y].push_back(x);//x是y的上级
		needs[y][x] = true;//反向建图
	}
	for (i = 0; i < E; i++)
	{
		memset(flag, 0, sizeof(flag));
		flag[i] = 1;
		dfs(i, i);//反向寻找所有与i点有关的上级
	}
	for (i = 0; i < E; i++)
	{
		for (j = 0; j < E; j++)
		{
			if (needs[i][j] != true && i != j)//needs[i][j]为flase意味着j升职与否与i没有关系
			{
				noneed[j]++;//意味着计算有多少点不需要j升职后再升职
			}
			if (needs[i][j] == true)
			{
				need[i]++;//意味着有多少人要先于i点升职
			}
		}
	}
	l = 0;
	r = 0;
	ans = 0;
	for (i = 0; i < E; i++)
	{
		if (noneed[i] < A)//意味着i点与多少人没有关系
		{
			l++;
		}
		if (noneed[i] < B)
		{
			r++;
		}
		if (need[i] >= B)//意味着如果在i点之前需要升职的人多于[A,B]的范围,他将永远没办法升职
		{
			ans++;
		}
	}
	cout << l << endl;
	cout << r << endl;
	cout << ans << endl;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值