POJ 1511 Invitation Cards 【dijkstra + 堆優化】

POJ 1511 Invitation Cards

原題鏈接:vjudge傳送門

題目大意:
求1號點到各個點的最短距離,以及各個點到1號點的最短距離,相加即可。題目保證是連通圖

具體思路:
圖中所有點到指定點的最短距離可以轉化爲求指定點到所有點的最短距離
因此用正反向存圖+2次Dijkstra,數據量很大,用堆優化

隨便說點:
做這道題我真的體會到鏈式前向星的好處,
一開始用vector前向星存圖+dijkstra+優先隊列(堆優化) TLE
緊接着用vector前向星存圖+spfa TLE
最後很無奈查了一下鏈式前向星存圖+dijkstra+優先隊列才ac

具體代碼:

//鏈式前向星存圖+dijkstra+優先隊列
#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const int N = 1000005, M = 1000005*2;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct Node {
	int to, next;
	LL w;
}edg[M];

int c, n, m, len, choice;
LL d[N],rd[N];
int head[N], rhead[N];
int visit[N];
void add(int h[], int u, int v, LL w) {
	edg[len].w = w;
	edg[len].to = v;
	edg[len].next = h[u];
	h[u] = len++;
}

struct cmp {
	bool operator()(int a, int b)
	{
		if(choice==1)	//代表正向dij的比較
			return d[a] > d[b];	//這比較函數,漲見識,可以用到全局變量
		return rd[a] > rd[b];
	}
};

LL dijkstra(LL d[], int head[])
{
	memset(visit, 0, sizeof(visit));
	priority_queue<int, vector<int>, cmp> q;

	d[1] = 0;
	q.push(1);	//一開始1號入隊,然後通過1號把,其它非無窮的點入隊
	while (q.size())
	{
		int t = q.top();
		q.pop();
		if (visit[t])continue;	//避免重複更新,也可以在下方push前判斷,避免重複入隊進行更新
		visit[t] = 1;
		for (int i = head[t]; i; i = edg[i].next)
		{
			int v = edg[i].to;
			LL w = d[t] + edg[i].w;
			if (d[v] > w) {
				d[v] = w;
				q.push(v);//被更新,入隊列參與最小堆操作
			}

		}
	}
	LL sum = 0;
	for (int i = 1; i <= n; i++)
		sum += d[i];
	return sum;
}
int main()
{
	scanf("%d", &c);
	while (c--)
	{
		len = 1;
		scanf("%d%d", &n, &m);
		memset(head, 0, sizeof(head));
		memset(rhead, 0, sizeof(rhead));
		for (int i = 1; i <= m; i++)
		{
			int s, d;
			LL p;
			scanf("%d%d%lld", &s, &d, &p);
			add(head, s, d, p);
			add(rhead, d, s, p);
		}
		memset(d, 0x3f, sizeof(d));
		memset(rd, 0x3f, sizeof(rd));
		choice = 1;
		LL sum = dijkstra(d, head);
		choice = 0;
		sum += dijkstra(rd, rhead);
		printf("%lld\n", sum);
	}
	return 0;
}

分割線


最後不才的附上TLE的代碼

//dijkstra
#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;
typedef long long LL;
const int N = 1000005;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct Node {
	int to;
	LL w;
	Node(int d, LL p) { to = d, w = p; }
};
//vector<Node> maps[N];
//vector<Node> rmaps[N];
int c, n, m;
LL d[N];
int visit[N];
struct cmp {
	bool operator()(int a, int b)
	{
		return d[a] > d[b];	//這比較函數,漲見識,可以用到全局變量
	}
};

LL dijkstra(vector<vector<Node> > maps)
{
	memset(visit, 0, sizeof(visit));
	for (vector<Node>::iterator it = maps[1].begin(); it != maps[1].end(); it++)
		d[it->to] = it->w;
	d[1] = 0;
	priority_queue<int, vector<int>,cmp> q;
	q.push(1);	//一開始1號入隊,然後通過1號把,其它非無窮的點入隊
	while (q.size())
	{
		int t = q.top();
		q.pop();
		visit[t] = 1;
		for (vector<Node>::iterator it = maps[t].begin(); it!= maps[t].end(); it++)
		{
			if (!visit[it->to])
			{
				d[it->to] = min(d[it->to], d[t] + it->w);
				q.push(it->to);	//被更新,入隊列參與最小堆操作
			}
		}
	}
	LL sum= 0;
	for (int i = 1; i <= n; i++)
			sum += d[i];
	return sum;
}

int main()
{
	scanf("%d", &c);
	while (c--)
	{	
		scanf("%d%d", &n, &m);
		vector<vector<Node> > maps(n+1);	//stl前向星存圖
		vector<vector<Node> > rmaps(n+1);	//stl前向星存圖
		memset(d, 0x3f, sizeof(d));
		for (int i = 1; i <= m; i++)
		{
			int s, d;
			LL p;
			scanf("%d%d%lld", &s, &d, &p);
			maps[s].push_back(Node(d, p));
			rmaps[d].push_back(Node(s, p));
		}
		LL sum = dijkstra(maps);
		memset(d, 0x3f, sizeof(d));
		sum+=dijkstra(rmaps);
		printf("%lld\n", sum);
	}
	return 0;
}
//spfa
#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;
typedef long long LL;
const int N = 1000005;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct Node {
	int to;
	LL w;
	Node(int d, LL p) { to = d, w = p; }
};
//vector<Node> maps[N];
//vector<Node> rmaps[N];
int c, n, m;
LL d[N];
int visit[N];
struct cmp {
	bool operator()(int a, int b)
	{
		return d[a] > d[b];
	}
};

LL spfa(vector<vector<Node> > maps)
{
	memset(visit, 0, sizeof(visit));
	
	queue<int> q;
	q.push(1);
	d[1] = 0;
	visit[1] = 1;
	while (q.size())
	{
		int t = q.front();
		q.pop();
		visit[t] = 0;
		for (vector<Node>::iterator it = maps[t].begin(); it!= maps[t].end(); it++)
		{
			if (d[it->to] > d[t] + it->w) {
				d[it->to] = d[t] + it->w;
				if (!visit[it->to]) {
					q.push(it->to);
					visit[it->to] = 1;
				}
			}

		}
	}
	LL sum= 0;
	for (int i = 1; i <= n; i++)
			sum += d[i];
	return sum;
}

int main()
{
	scanf("%d", &c);
	while (c--)
	{	
		scanf("%d%d", &n, &m);
		vector<vector<Node> > maps(n+1);	//stl前向星存圖
		vector<vector<Node> > rmaps(n+1);	//stl前向星存圖
		memset(d, 0x3f, sizeof(d));
		for (int i = 1; i <= m; i++)
		{
			int s, d;
			LL p;
			scanf("%d%d%lld", &s, &d, &p);
			maps[s].push_back(Node(d, p));
			rmaps[d].push_back(Node(s, p));
		}
		LL sum = spfa(maps);
		memset(d, 0x3f, sizeof(d));
		sum+= spfa(rmaps);
		printf("%lld\n", sum);
	}
	return 0;
}
發佈了69 篇原創文章 · 獲贊 34 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章