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;
}