您的位置:首页 > 其它

[POJ 1511]Invitation Cards[链式前向星][SPFA]

2015-10-20 01:35 225 查看
题目链接:[POJ 1511]Invitation Cards[链式前向星][SPFA]

题意分析:

每天从点1都会有n−1个孩子需要到点2 ~ n去做事。现在给出a−>b的费用,问,每天从2 ~ n这些点来回一趟最少需要多少钱?

解题思路:

考虑本题边的个数和点的个数均 <=1e6。可以使用SPFA进行操作,使用链式前向星存储图。

这里处理来回距离有一个小技巧,spfa可以求得点1到所有点的最短距离;那么把整个图转置一下(所有边都取它的反向边建图),再求1到所有点的最短距离,此时的最短距离就是所有点到1的最短距离。

为什么要用链式前向星存储图呢?因为本题是一个稀疏图,使用邻接矩阵极限样例情况下占用空间至少为1e6,而链式前向星最多1e6。其次,邻接矩阵的vector调用,需要申请空间,无形中又拖慢了速度。而链式前向星只需要调用已有数组。

个人感受:

一直不能理解链式前向星有什么好的,结果这题就教做人了。死活就是T,改用链式前向星就A了。可怕 山口山

具体代码如下:

#include<cstdio>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;

const ll INF = 0x7f7f7f7f;
const int MAXN = 1e6 + 111;

struct Edge{
int to, next;
ll val;
}edge[2][MAXN];

ll dis[2][MAXN];
int head[2][MAXN], cnt;
bool in[MAXN];

void make_map(int from, int to, ll v, int sta)
{
edge[sta][cnt].to = to;
edge[sta][cnt].val = v;
edge[sta][cnt].next = head[sta][from];
head[sta][from] = cnt;
}

void spfa(int s, int sta)
{
dis[sta][s] = 0;
queue<int> q;
q.push(s);
in[s] = 1;
while (q.size())
{
int cur = q.front(); q.pop(); in[cur] = 0;
for (int i = head[sta][cur]; ~i; i = edge[sta][i].next)
{
Edge &e = edge[sta][i];
if (dis[sta][e.to] > dis[sta][cur] + e.val)
{
dis[sta][e.to] = dis[sta][cur] + e.val;
if (!in[e.to])
{
in[e.to] = 1;
q.push(e.to);
}
}
}
}
}

int main()
{
int kase, p, q, u, v, w; scanf("%d", &kase);
while (kase --)
{
scanf("%d%d", &p, &q);
for (int i = 1; i <= p; ++i)
{
dis[0][i] = dis[1][i] = INF;
head[0][i] = head[1][i] = -1;
}
cnt = 0;
while (q --)
{
scanf("%d%d%d", &u, &v, &w);
make_map(u, v, w, 0);
make_map(v, u, w, 1);
++cnt;
}
spfa(1, 0);
spfa(1, 1);
ll ans = 0;
for (int i = 2; i <= p; ++i)
{
// cout << dis[0][i] << ' ' << dis[1][i] << '\n';
ans += dis[0][i] + dis[1][i];
}
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: