Poj 1511- Invitation Cards(Spfa+邻接表)

这题第一感觉就是Floyd:方便快捷,也很直接。sum+=d[1][i]+d[i][1]  (i---- 1->n);

但显然悲剧超时,然后就想到Floyd的优化算法Spfa。一般的都会用上队列,比如vector确实好用,但这题太坑,卡vector超时,然后听取了其他人的想法用邻接表解决了。

#include<stdio.h>

#define MAXN 1000010
#define MOD 1000007
#define inf 10000000000000LL

typedef long long ll;

struct etype
{
    int to;
    int w;
    int next;
}e[MAXN],re_e[MAXN];

int list1[MAXN],list2[MAXN];
ll min1[MAXN],min2[MAXN];

int q[MOD];     //相当于队列
bool inq[MAXN];

void spfa(int n,int s,int *list,etype * edge,ll *min)
{
    for (int i=1;i<=n;i++)
        min[i]=inf,inq[i]=0;
    min[s]=0,inq[s]=1,q[0]=s;
    int beg=0,end=1;
    while(beg!=end)        //就像是!q.empty()
    {
        int t=q[beg];
        beg=(beg+1)%MOD;
        for (int p=list[t];p!=-1;p=edge[p].next)          //其实这里用了邻接表和数组代替队列感觉就像是Dijkstra的思想了
        {
            int j=edge[p].to,w=edge[p].w;
            if (min[j]>min[t]+w)
            {
                min[j]=min[t]+w;
                if (!inq[j])
                    inq[j]=1,q[end]=j,end=(end+1)%MOD;
            }
        }
    }
}

int main()
{
    int test;
    scanf("%d",&test);
    while(test--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
            list1[i]=-1,list2[i]=-1;
        for (int i=0;i<m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            e[i].to=b,e[i].w=c,e[i].next=list1[a],list1[a]=i;    // 注意这个邻接表list[i]实际上就是q[a].push_back(b);最后配合next实现,而它是后往前,vector是前往后
            re_e[i].to=a,re_e[i].w=c,re_e[i].next=list2[b],list2[b]=i;  //实际上就是把图反过来 求学生回来的情况,大家可以画图模拟一下
        }
        spfa(n,1,list1,e,min1);
        spfa(n,1,list2,re_e,min2);
        ll ans=0;
        for (int i=1;i<=n;i++)
            ans+=(min1[i]+min2[i]);
        printf("%I64d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值