缩点+拓扑/迪杰斯特拉 WA On #3 & #11
查看原帖
缩点+拓扑/迪杰斯特拉 WA On #3 & #11
677356
syzyc楼主2024/11/24 16:13

本人已用 SPFA 通过此题,但是若将 SPFA 换成 Dijkstra 或 拓扑排序总会 WA On #3 & #11。

求问这俩没有正确性吗,还是我写错了?

缩点 + Dijkstra 代码:

#include <bits/stdc++.h>

#define mkpr make_pair
#define fir first
#define sec second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 5e5 + 7;
const int inf  = 0x3f3f3f3f;

int n, m, s, p;
int money[maxn], bar[maxn];
vector<int> e[maxn], scce[maxn];

int scc[maxn], siz[maxn], scc_cnt;
int dfn[maxn], low[maxn], dfn_cnt;
int sta[maxn], top;
bool ins[maxn];
void tarjan(int u) {
	low[u] = dfn[u] = ++dfn_cnt;
	sta[++top] = u, ins[u] = 1;
	
	for (int v : e[u]) {
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		} else if (ins[v]) {
			low[u] = min(low[u], dfn[v]);
		}
	}
	
	if (low[u] == dfn[u]) {
		int v; ++scc_cnt;
		do {
			v = sta[top--], ins[v] = 0;
			siz[scc_cnt] += money[v];
			scc[v] = scc_cnt;
		} while (v != u);
	}
}

int dis[maxn];
bool vis[maxn];
priority_queue<pii> pq;
void dij() {
	memset(dis, -inf, sizeof(dis));
	dis[scc[s]] = siz[scc[s]];
	pq.push(mkpr(dis[scc[s]], scc[s]));
	while (pq.size()) {
		int u = pq.top().sec; pq.pop();
		
		if (vis[u]) continue;
		vis[u] = 1;
		for (int v : scce[u]) {
			if (dis[v] < dis[u] + siz[v]) {
				dis[v] = dis[u] + siz[v];
				pq.push(mkpr(dis[v], v));
			}
		}
	}
}

unordered_set<int> uni[maxn];
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[u].push_back(v);
	}
	for (int i = 1; i <= n; ++i)
	    scanf("%d", money + i);
	scanf("%d%d", &s, &p);
	for (int i = 1; i <= p; ++i)
	    scanf("%d", bar + i);

    tarjan(s);
		
	for (int u = 1; u <= n; ++u) {
		for (int v : e[u]) {
			if (scc[u] == scc[v]) continue;
			if (uni[scc[u]].count(scc[v])) continue;
			uni[scc[u]].insert(scc[v]);
			scce[scc[u]].push_back(scc[v]);
		}
	}
	
	dij();
		
	int ans = 0;
	for (int i = 1; i <= p; ++i) 
		ans = max(ans, dis[scc[bar[i]]]);
    printf("%d\n", ans);
	return 0;
} 

缩点 + 拓扑排序代码:

#include <bits/stdc++.h>

#define mkpr make_pair
#define fir first
#define sec second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 5e5 + 7;
const int inf  = 0x3f3f3f3f;

int n, m, s, p;
int money[maxn], bar[maxn];
vector<int> e[maxn], scce[maxn];

int scc[maxn], siz[maxn], scc_cnt;
int dfn[maxn], low[maxn], dfn_cnt;
int sta[maxn], top;
bool ins[maxn];
void tarjan(int u) {
	low[u] = dfn[u] = ++dfn_cnt;
	sta[++top] = u, ins[u] = 1;
	
	for (int v : e[u]) {
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		} else if (ins[v]) {
			low[u] = min(low[u], dfn[v]);
		}
	}
	
	if (low[u] == dfn[u]) {
		int v; ++scc_cnt;
		do {
			v = sta[top--], ins[v] = 0;
			siz[scc_cnt] += money[v];
			scc[v] = scc_cnt;
		} while (v != u);
	}
}

int dp[maxn];
queue<int> q;
int ind[maxn];
void tps() {
    q.push(scc[s]);
    dp[scc[s]] = siz[scc[s]];
	while (q.size()) {
		int u = q.front(); q.pop();

		for (int v : scce[u]) {
			dp[v] = max(dp[v], dp[u] + siz[v]);
			if(--ind[v] == 0) q.push(v);
		}

	}
}

unordered_set<int> uni[maxn];
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[u].push_back(v);
	}
	for (int i = 1; i <= n; ++i)
	    scanf("%d", money + i);
	scanf("%d%d", &s, &p);
	for (int i = 1; i <= p; ++i)
	    scanf("%d", bar + i);

    tarjan(s);
		
	for (int u = 1; u <= n; ++u) {
		for (int v : e[u]) {
			if (scc[u] == scc[v]) continue;
			if (uni[scc[u]].count(scc[v])) continue;
			uni[scc[u]].insert(scc[v]);
			scce[scc[u]].push_back(scc[v]);
		}
	}
	
	tps();
		
	int ans = 0;
	for (int i = 1; i <= p; ++i) 
		ans = max(ans, dp[scc[bar[i]]]);
    printf("%d\n", ans);
	return 0;
} 
2024/11/24 16:13
加载中...