cf 427c Checkposts

CF 427c

题意

给定一个有向无自环图及每个点的点值,定义第 i 个 E-DCC的价值为此 E-DCC 中所有点权最小值 ai ,且满足点权最小的数量有 bi 个,求 ∑ i a i \sum_i a_i iai ∏ i b i \prod_ i b_i ibi

分析

不难想到对图进行缩点,然后求一下每一个 E-DCC 中最小值及其个数 输出即可

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
const int M = 3e5 + 10;

const int Mod = 1e9 + 7;

struct Node
{
	int from;
	int to;
	int next;
};

Node edge[M];
int head[N];
int tot;

int var[N];

int dfn[N];
int low[N];
bool instack[N];
stack <int> st;
int times;

int tar;
vector <int> v;
int col[N];

int v_c[N];
int cnt_c[N];

vector <int> in;
vector <int> mvar;
vector <int> edgesd[N];

void init()
{
	memset(head , -1 , sizeof(head));
	memset(dfn , -1 , sizeof(dfn));
	v.push_back(0);
	mvar.push_back(0);
	in.push_back(0);
}

void add(int x , int y)
{
	edge[++tot].to = y;
	edge[tot].from = x;
	edge[tot].next = head[x];
	head[x] = tot;
	return;
}

void tarjan(int x)
{
	dfn[x] = low[x] = ++times;
	st.push(x);
	instack[x] = true;
	for(int i = head[x] ; i != -1 ; i = edge[i].next)
	{
		if(dfn[edge[i].to] == -1)
		{
			tarjan(edge[i].to);
			low[x] = min(low[x] , low[edge[i].to]);
		}
		else if(instack[edge[i].to])
		{
			low[x] = min(low[x] , dfn[edge[i].to]);
		}
	}
	if(low[x] == dfn[x])
	{
		tar++;
		v.push_back(0);
		mvar.push_back(0);
		in.push_back(0);
		while(!st.empty())
		{
			int use = st.top();
			st.pop();
			instack[use] = false;
			col[use] = tar;
			v[tar] += var[use];
			if(use == x)
			{
				break;
			}
		}
	}
}

int main()
{
	init();
	int maxn = -1;
	int n , m;
	scanf("%d" , &n);
	for(int i = 1 ; i <= n ; i++)
	{
		scanf("%d" , &var[i]);
	}
	scanf("%d" , &m);
	int x , y;
	for(int i = 1 ; i <= m ; i++)
	{
		scanf("%d %d" , &x , &y);
		add(x , y);
	}
	for(int i = 1 ; i <= n ; i++)
	{
		if(dfn[i] == -1)
		{
			tarjan(i);
		}
	}
	memset(v_c , 0x3f , sizeof(v_c));
	for(int i = 1 ; i <= n ; i++)
	{
		v_c[col[i]] = min(v_c[col[i]] , var[i]);
	}
	for(int i = 1 ; i <= n ; i++)
	{
		if(var[i] == v_c[col[i]])
		{
			cnt_c[col[i]]++;
		}
	}
	long long ans = 1;
	long long cnt = 0;
	for(int i = 1 ; i <= tar ; i++)
	{
		ans *= (long long)cnt_c[i];
		ans %= Mod;
		cnt += v_c[i];
	}
	printf("%lld %lld" , cnt , ans);

	return 0;
}
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值