遍历(强连通)

第3题     遍历 查看测评数据信息

给定n个点,m条边的有向图,每个节点有一个权重v(i),你的任务是把n个点遍历一遍,点可以重复经过。允许的操作如下:每次你可以选择一个开始节点i,如果可以从i出发,最后可以回到i节点,那么你的花费为v(i)。

问:最少需要多少费用可以把n个节点遍历一遍,并且当费用最少时的方案数是多少?存在一个开始节点不同被视为两种不同的方案,由于方案数可能过大,所以请输出方案数对 10^9+7 取模的结果。

(注:这里每次可以从任何一个开始节点开始走回路。就是说一个回路走完了,下一个开始位置可以任选。)

对于 100% 的数据,1<= n <= 10^5,1<= m <= 3*10^5,0<= w(i) <= 10^9。

输入格式

 

第一行一个正整数 n。   

第二行 n 个正整数,表示每个点的点权 w(i)。  

第三行一个正整数 m。  

接下来 m 行,每行两个正整数 x,y,表示一条 x到y有一条有向边。

 

输出格式

 

输出一行两个整数,分别表示最小花费,和花费最小时的方案数。

 

输入/输出例子1

输入:

3

1 2 3

3

1 2

2 3

3 2

 

输出:

3 1

 

样例解释

 

 

比较简单,记录缩点后胖点内最小值即可,以及有几个最小值

 

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5, Mod=1e9+7;

int n, m, w[N], u1, v1;
int dfn[N], low[N], idx=0, cnt=0, id[N], Min[N];
long long Aans=0, Bans=0;
stack<int> st;
vector<int> a[N], b[N];
void dfs(int u)
{
	dfn[u]=low[u]=++idx;
	st.push(u);
	
	for (int i=0; i<a[u].size(); i++)
	{
		int v=a[u][i];
		if (!dfn[v])
		{
			dfs(v);
			low[u]=min(low[u], low[v]);
		}
		else if (!id[v]) low[u]=min(low[u], dfn[v]);
	}
	
	if (dfn[u]==low[u])
	{
		cnt++;
		while (st.top()!=u)
		{
			id[st.top()]=cnt;
			b[cnt].push_back(w[st.top()]);
			Min[cnt]=min(Min[cnt], w[st.top()]);
			st.pop();
		}
		id[st.top()]=cnt;
		b[cnt].push_back(w[st.top()]);
		Min[cnt]=min(Min[cnt], w[st.top()]);
		st.pop();
	}
}
int main()
{
	for (int i=0; i<N-5; i++) Min[i]=1e9+5;
	
	scanf("%d", &n);
	for (int i=1; i<=n; i++) scanf("%d", &w[i]);
	scanf("%d", &m);
	for (int i=1; i<=m; i++)
	{
		scanf("%d%d", &u1, &v1);
		a[u1].push_back(v1);
	}
	
	for (int i=1; i<=n; i++)
		if (!dfn[i]) dfs(i);
	/*
	for (int i=1; i<=cnt; i++)
	{
		printf("%d: {", i);
		for (int j=0; j<b[i].size(); j++) printf("%d ", b[i][j]);
		printf("}\n");
	}*/
	
	Bans=1;
	for (int i=1; i<=cnt; i++)
	{
		int s=0;
		for (int j=0; j<b[i].size(); j++)
			if (b[i][j]==Min[i]) s++;
			
		Bans=(Bans*s)%Mod;	
		Aans+=Min[i];
	}
	
	printf("%lld %lld", Aans, Bans);
	return 0;
}
/*
1: {3 2 }
2: {1 }

3
1 2 3
3
1 2
2 3
3 2
*/

  

posted @ 2024-07-18 19:18  cn是大帅哥886  阅读(12)  评论(0)    收藏  举报