求助spfa问题
查看原帖
求助spfa问题
335264
Liooooo楼主2023/5/21 13:31

本题我在使用spfa求势能h时需要对h赋初始值才能使答案正确

但如果使用Bellman-Ford则不需要给h赋初值

难道不是只关心势能的差值吗?

为什么spfa时对h的初值会有一定要求?

#include <bits/stdc++.h>
using namespace std;

//#define int long long

inline int read()
{
	int a = 0, b = 1; char c = getchar();
	while(c < '0' || c > '9') { if(c == '-') b = -1; c = getchar(); }
	while(c <= '9' && c >= '0') { a = a * 10 + c - 48; c = getchar(); }
	return a * b;
}

inline void write(int n)
{
    if(n > 9) write(n / 10);
    putchar(n % 10 + 48);
}

#define pii pair<int, int>

const int N = 3e3 + 20;

int n, m, u, v, w;
int h[N], dis[N], vis[N], flag[N];
int flagd[N];
vector<pii> e[N];

void spfa()
{
	memset(h, 10, sizeof(h)); h[0] = 0;
   //不加上面这一行就会出错
	for(int i = 1 ; i <= n ; ++ i) e[0].push_back(make_pair(0, i));
	queue<int> q1;
	q1.push(0);
	while(!q1.empty())
	{
		int t = q1.front(); q1.pop(); flag[t] = 0;
		for(auto _ : e[t])
		{
			int d = h[t] + _.first;
			if(d < h[_.second])
			{
				h[_.second] = d; vis[_.second] = vis[t] + 1;
				if(vis[_.second] == n + 1)
				{
					printf("-1\n");
					exit(0);
				}
				if(flag[_.second] == 0)
				{
//					vis[_.second] ++;
//					if(vis[_.second] == n + 1)
//					{
//						printf("-1\n");
//						exit(0);
//					}
					q1.push(_.second);
					flag[_.second] = 1;
				}
			}
		}
	}
	return;
}

void dj(int s)
{
	priority_queue<pii, vector<pii>, greater<pii> > q2;
	memset(flagd, 0, sizeof(flagd)); memset(dis, 0x3f, sizeof(dis)); dis[s] = 0;
	q2.push(make_pair(0, s));
	while(!q2.empty())
	{
		auto t = q2.top(); q2.pop();
		if(flagd[t.second]) continue;
		else flagd[t.second] = 1;
		for(auto _ : e[t.second])
		{
			int d = dis[t.second] + _.first + h[t.second] - h[_.second], id = _.second;
			if(d < dis[id])
			{
				dis[id] = d;
				q2.push(make_pair(d, id));
			}
		}
	} 
	return;
}

void bf()
{
	for(int i = 1 ; i <= n ; ++ i)
	{
		bool found = 0;
		for(int j = 1 ; j <= n ; ++ j)
		{
			for(auto _ : e[j])
			{
				if(h[j] + _.first < h[_.second])
				{
					found = 1;
					h[_.second] = h[j] + _.first;
				}
			}
		}
		if(found && i == n)
		{
			printf("-1\n");
			exit(0);
		}
	}
}

int main()
{
	//ios::sync_with_stdio(false);
	n = read(); m = read();
	for(int i = 1 ; i <= m ; ++ i)
	{
		u = read(); v = read(); w = read();
		e[u].push_back(make_pair(w, v));
	}
	spfa();
	//bf();
	for(int i = 1 ; i <= n ; ++ i)
	{
		long long ans = 0;
		dj(i);
		for(int j = 1 ; j <= n ; ++ j)
		{
			if(dis[j] == dis[0]) ans += 1ll * j * 1e9;
			else if(i == j) continue;
			else ans += 1ll * j * (dis[j] - h[i] + h[j]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}
//start coding at  :
//finish debugging at  :

2023/5/21 13:31
加载中...