缩点模板,建议降绿
查看原帖
缩点模板,建议降绿
658786
STUDENT00楼主2022/11/11 21:44

缩点+乘法原理,建议降绿

#include<bits/stdc++.h>
using namespace std;
int n,m,a[100010],dfn[100010],low[100010],fa[100010],mins[100010],cnt,tot[100010],ans,sum=1;
bool vis[100010];
stack<int> st;
vector<int> w[100010];
void tarjan(int now){
	vis[now]=1;
	st.push(now);
	dfn[now]=low[now]=++cnt;
	for(int i=0;i<w[now].size();i++){
		int t=w[now][i];
		if(!dfn[t]){
			tarjan(t);
			low[now]=min(low[now],low[t]);
		}else if(vis[t]) low[now]=min(low[now],dfn[t]);
	}
	if(low[now]==dfn[now]){
		int y;
		do{
			y=st.top();
			st.pop();
			vis[y]=0;
			if(a[y]<mins[now]){
				mins[now]=a[y];
				tot[now]=1;
			}else if(a[y]==mins[now]) tot[now]++;
			fa[y]=now;
		}while(now!=y);
	}
}
int main(){
	memset(mins,127,sizeof(mins));
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	scanf("%d",&m);
	while(m--){
		int x,y;
		scanf("%d%d",&x,&y);
		w[x].push_back(y);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]) tarjan(i);
	}
	for(int i=1;i<=n;i++){
		if(fa[i]==i){
			ans+=mins[i];
			sum*=tot[i];
		}
	}
	printf("%d %d",ans,sum);
	return 0;
}
2022/11/11 21:44
加载中...