Poj 3013 Big Christmas Tree

来源:互联网 发布:守望先锋显示数据 编辑:程序博客网 时间:2024/06/05 18:28

题目链接:http://poj.org/problem?id=3013

本题是最短路问题。

但是较特殊的一点是边少点多。构建临界矩阵不合理,因为是稀疏图,且点较多,会爆栈。

所以,正确的做法使用邻接表,邻接表又分为基于点的邻接表和基于边的,对于本题而言,我们用基于边的链式前向星较好。

链式前向星也就是我们经常说的池子法

另外,对于最短路的处理,我们用SPFA较好。

所以,综合,本题练习基于前向星的SPFA

其实,SPFA处理最短路问题,不过是队列优化的Bellman-ford而已,具体参考刘汝佳《算法竞赛入门经典》205页。

代码:

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <vector>#include <queue>#include <algorithm>using namespace std;#define  ll __int64#define INF ((ll)1<<63)-1#define Maxn 50005struct Edge{    int s;    int t;    ll price;    int next;};ll w[Maxn];int first[Maxn];int used[Maxn];//当前节点在不在队列中ll dist[Maxn];Edge e[Maxn<<1];void spfa(int s){    queue<int> q;    memset(used,0,sizeof(used));    used[s] = 1;    q.push(s);    while(!q.empty())    {        int u = q.front();        q.pop();        used[u] = 0;        for(int i=first[u]; i!=-1; i=e[i].next)        {            int v = e[i].t;            ll price = e[i].price;            if(dist[v] - price > dist[u])            {                dist[v] = dist[u] + price;                if(used[v] == 0)                {                    used[v] = 1;                    q.push(v);                }            }        }    }}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif    int t;    int eNum,vNum;    int a,b;    ll c;    scanf(" %d",&t);    while(t--)    {        scanf(" %d %d",&vNum,&eNum);        for(int i=1; i<=vNum; i++)        {            scanf(" %I64d",&w[i]);            dist[i] = INF;        }        dist[1] = 0;        memset(first,-1,sizeof(first));        for(int i=0; i<=2*eNum; i++)        {            e[i].next = -1;        }        int cnt = 0;        for(int i=0; i<eNum; i++)        {            scanf(" %d %d %I64d",&a,&b,&c);            e[cnt].s = a,e[cnt].t = b,e[cnt].price = c;            e[cnt].next = first[a];            first[a] = cnt;            cnt++;            e[cnt].s = b,e[cnt].t = a,e[cnt].price = c;            e[cnt].next = first[b];            first[b] = cnt;            cnt++;        }        spfa(1);        int flag = 0;        ll ans = 0;        for(int i=1; i<=vNum; i++)        {            if(dist[i] == INF)            {                flag = 1;                break;            }            ans += dist[i] * w[i];        }        if(flag == 0)            printf("%I64d\n",ans);        else            printf("No Answer\n");    }}


原创粉丝点击