标签:强连通分量 code clu 个数 经验 www href include 答案
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int mod=1e9+7;
const int N=100005;
const int M=300005;
ll ans1,ans2=1;
int n,m,w[N],a[M],b[M];
int tim,top,num,dfn[N],low[N],st[N],color[N],val[N][2];
//val[i][0]表示第i个强连通分量的费用最小值
//val[i][1]表示第i个强连通分量的费用最小值的个数
int tot,head[N],nxt[M],to[M];
inline void add(int a,int b){
nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
}
inline void tarjan(int u){
dfn[u]=low[u]=++tim;st[++top]=u;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!color[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
color[u]=++num;
val[num][0]=w[u];val[num][1]=1;
while(st[top]!=u){
color[st[top]]=num;
if(w[st[top]]<val[num][0]){
val[num][0]=w[st[top]];
val[num][1]=1;
}
else if(w[st[top]]==val[num][0])++val[num][1];
--top;
}
--top;
}
}
int main(){
n=read();for(int i=1;i<=n;++i)w[i]=read();
m=read();
for(int i=1;i<=m;++i){
a[i]=read();b[i]=read();
add(a[i],b[i]);
}
for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
for(int i=1;i<=num;++i){
ans1+=val[i][0];//累加每个强连通分量的费用最小值
ans2=(ans2*val[i][1])%mod;//乘法原理计算方案
}
printf("%lld %lld\n",ans1,ans2);
return 0;
}
标签:强连通分量 code clu 个数 经验 www href include 答案
原文地址:https://www.cnblogs.com/PPXppx/p/11579263.html