poj1511

这一题学到的东西太多了

1.大数组不能开在函数中,要使用全局变量

2.bellman_ford算法

3.c语言中struct不能有构造函数,开数组不能使用const的值作为大小,而要用define.

4.代替vector的建图方法,数组模拟链表法,map[i]存第i个点的第一条边在e中的下标。e用来存边,next记录该点的下一条边的坐标。

5.使用vector的效率极低。

本题只需建正反两个图,分别求距离,把所有点的距离加起来就是答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

const int maxn = 1000000;

struct Edge
{
	int v, w, nxt;
	Edge()
	{
	}
	Edge(int vv, int ww, int nn) :
		v(vv), w(ww), nxt(nn)
	{
	}
} e[maxn], ope[maxn];
int map[maxn], opmap[maxn];
int p, q;
long long ans;
long long dist[maxn];

void init()
{
	ans = 0;
	scanf("%d%d", &p, &q);
	memset(map, -1, sizeof(map));
	memset(opmap, -1, sizeof(opmap));
	for (int i = 0; i < q; i++)
	{
		int a, b, w;
		scanf("%d%d%d", &a, &b, &w);
		a--;
		b--;
		e[i] = (Edge(b, w, map[a]));
		map[a] = i;
		ope[i] = (Edge(a, w, opmap[b]));
		opmap[b] = i;
	}
}

bool relax(long long *dist, int u, Edge &e)
{
	if (dist[e.v] > dist[u] + e.w || dist[e.v] == -1)
	{
		dist[e.v] = dist[u] + e.w;
		return true;
	}
	return false;
}

void bellman(int *map, Edge *e)
{
	int q[maxn], front = 0, rear = 1;
	bool vis[maxn];

	memset(dist, -1, sizeof(dist));
	memset(vis, 0, sizeof(vis));
	q[0] = 0;
	dist[0] = 0;
	vis[0] = true;
	while (front != rear)
	{
		int temp = q[front++];
		if (front == maxn)
			front = 0;
		vis[temp] = false;
		for (int i = map[temp]; i != -1; i = e[i].nxt)
		{
			if (relax(dist, temp, e[i]) && !vis[e[i].v])
			{
				q[rear++] = e[i].v;
				if (rear == maxn)
					rear = 0;
				vis[e[i].v] = true;
			}
		}
	}
	for (int i = 0; i < p; i++)
		ans += dist[i];
}

int main()
{
	//freopen("D:\\t.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while (t--)
	{
		init();
		bellman(map, e);
		bellman(opmap, ope);
		printf("%I64d\n", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/rainydays/p/1948672.html