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

来源:互联网 发布:qq采集软件 编辑:程序博客网 时间:2024/06/16 13:46

题目链接:[POJ 1511]Invitation Cards[链式前向星][SPFA]
题意分析:
每天从点1都会有n1个孩子需要到点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 longusing 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;}
0 0