POJ1511 Invitation Cards

来源:互联网 发布:java序列化 编辑:程序博客网 时间:2024/05/23 12:35

最短路

题目传送门

题目大意:给你n个顶点,m条有向边,求从起点1出发到各个顶点后再回到起点所需最小代价。

思路:存两张图,一张正着存,一张倒着存。然后分别在这两张图里跑spfa,把结果加起来就行啦!
倒着存从1开始跑,其实就是求从各个顶点到1的最小代价,再加上正着存的就是答案啦!

贴个代码:

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 1000000using namespace std;struct edge{    int next;    int to;    int dis;};int h1[MAXN+5],h2[MAXN+5];int que[2*MAXN+5];long long dis1[MAXN+5],dis2[MAXN+5];bool f[MAXN+5];int t,n,m,k,u,v,d;edge ed1[MAXN+5],ed2[MAXN+5];void read(int x,int y,int z){    k++;     ed1[k].next=h1[x]; ed1[k].to=y; ed1[k].dis=z; h1[x]=k;    ed2[k].next=h2[y]; ed2[k].to=x; ed2[k].dis=z; h2[y]=k;}void spfa111(){    memset(dis1,0x7f,sizeof(dis1));    memset(f,false,sizeof(f));    int r=0,w=1;    que[1]=1; f[1]=true; dis1[1]=0;    while (r!=w){        r=(r+1)%MAXN;        int x=que[r];        f[x]=false;        for (int i=h1[x];i;i=ed1[i].next)            if (dis1[ed1[i].to]>dis1[x]+ed1[i].dis){                dis1[ed1[i].to]=dis1[x]+ed1[i].dis;                if (!f[ed1[i].to]){                    w=(w+1)%MAXN;                    que[w]=ed1[i].to;                    f[ed1[i].to]=true;                }            }    }}void spfa222(){    memset(dis2,0x7f,sizeof(dis2));    memset(f,false,sizeof(f));    int r=0,w=1;    que[1]=1; f[1]=true; dis2[1]=0;    while (r!=w){        r=(r+1)%MAXN;        int x=que[r];        f[x]=false;        for (int i=h2[x];i;i=ed2[i].next)            if (dis2[ed2[i].to]>dis2[x]+ed2[i].dis){                dis2[ed2[i].to]=dis2[x]+ed2[i].dis;                if (!f[ed2[i].to]){                    w=(w+1)%MAXN;                    que[w]=ed2[i].to;                    f[ed2[i].to]=true;                }            }    }}int main(){    scanf("%d",&t);    while (t--){        memset(h1,0,sizeof(h1));        memset(h2,0,sizeof(h2));        k=0;        scanf("%d%d",&n,&m);        for (int i=1;i<=m;i++){            scanf("%d%d%d",&u,&v,&d);            read(u,v,d);        }        spfa111();        spfa222();        long long ans=0;        for (int i=1;i<=n;i++)            ans=ans+dis1[i]+dis2[i];        printf("%lld\n",ans);    }    return 0;}
原创粉丝点击