Tarjan WA on #2 #9 #10求助
查看原帖
Tarjan WA on #2 #9 #10求助
759274
Stevehim楼主2023/7/9 20:55
#include <bits/stdc++.h>
#define maxe 500050
#define maxv 500050
using namespace std;
vector<int> G[maxe];
const int mod = 1e9 + 7;
const int inf = 1e9 + 1;
int n, m;
int cnts = 1;
int low[maxv]; //为根节点的子树最近访问
int dfn[maxv];
int belong[maxv];
int s[maxv];
int top = 0;
int cnt = 0, tot = 0;
int num[maxv]; //每个强连通分量点的个数
int outdegree[maxv]; //记录出度
int indegree[maxv];
bool vis[maxv];
int sum[maxv];
int w[maxv]; //点权
long long ans1,ans2;
void tarjan(int x) {
	int c;
	low[x] = dfn[x] = ++cnt; //记录初始的时间戳和最近访问
	s[++top] = x; //入栈
	vis[x] = true; //标记访问
	for (int u = 0; u < G[x].size(); u++) {
		c = G[x][u]; //好写一些
		if (!dfn[c]) { //没有访问
			tarjan(c); //递归下去
			low[x] = min(low[x], low[c]); //进行判定
		} else if (vis[c]) { //已经访问过了
			low[x] = min(low[x], dfn[c]);
		}
	}
	if (dfn[x] == low[x]) { //如果等于证实是一个强连通分量,因为压根没做改动
		tot++;
		c = -1;
		sum[tot] = inf;
		while (x != c) { //找出强连通分量
			sum[tot] = min(sum[tot],w[s[top]]);
			c = s[top--]; //取出
			belong[c] = tot; //表上序号
			if(w[c] < sum[tot]){ //更新
				sum[tot] = w[c];
				num[tot] = 0; //重置
			}
			if(w[c] == sum[tot]) num[tot]++; //相等的数值则可能性加1
			vis[c] = false;
		}
	}
}
int u,v;
int main() {
	// 	freopen("1.in","r",stdin);
//	memset(sum, 127, sizeof sum);
//	memset(num,1,sizeof num);
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> w[i];
	cin >> m;
	for(int i = 1; i <= m; i++){
		cin >> u >> v;
		G[u].push_back(v);
	}
	for (int i = 1; i <= n; i++) {
		if (!dfn[i]) { //选择没有的
			tarjan(i);
		}
	}
//	for(int i = 1; i <= n; i++){
//		for(int u = 0; u < G[i].size(); u++){
//			if(belong[i] != belong[G[i][u]]){
//				outdegree[belong[i]]++;
//				indegree[G[i][u]]++;
//			}
//		}
//	}
	ans2 = 1;
	for(int i = 1; i <= tot; i++){
//		if(!indegree[i]){
			ans1 += sum[i];
			ans2 *= num[i];
			ans2 %= mod;
//		}
	}
	cout<< ans1 << ' ' << ans2;
	return 0;
}
2023/7/9 20:55
加载中...