POJ-1511-Invitation Cards
http://poj.org/problem?id=1511
題意是給出一些邊,求第一個點到其他各點距離之和+其他各點到第一個點的距離之和的最小值,求兩次單源最短距離即可,第一次求出第一個點到其他各點距離的最小值,第二次將所有的有向邊反向,再求一次第一個點到其他各點距離的最小值即是原圖中其他各點到第一個點的最小距離,題目的資料比較多,用spfa
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define N 1000010#define MAX 0x7fffffffint head[N],nextt[N],key[N],num[N],visit[N];int t;__int64 dis[N];int nodenum,edgenum;struct cam //有向邊{int st,ed;int v;}edge[N];void add(int st,int ed,int v) {key[t]=v;nextt[t]=head[st]; //以u為起點的上一條邊num[t]=ed;head[st]=t++; //以st為起點最近的一條邊}void init(){t=0;memset(head,-1,sizeof(head));for(int i=1;i<=nodenum;i++)dis[i]=MAX;}__int64 spfa(int start){ __int64 total=0;int temp;queue<int>q;while(!q.empty())q.pop();memset(visit,0,sizeof(visit));dis[start]=0;visit[start]=1;q.push(start);while(!q.empty()){temp=q.front();q.pop();visit[temp]=0;for(int i=head[temp];i!=-1;i=nextt[i]){if(dis[num[i]]>dis[temp]+key[i]){dis[num[i]]=dis[temp]+key[i];if(!visit[num[i]]){q.push(num[i]);visit[num[i]]=1;}}}}for(int i=1;i<=nodenum;i++)total+=dis[i];return total;}int main(){int top,cas;__int64 ans;scanf("%d",&cas);while(cas--){top=ans=0;scanf("%d%d",&nodenum,&edgenum);init();for(int i=0;i<edgenum;i++){scanf("%d%d%d",&edge[top].st,&edge[top].ed,&edge[top].v);add(edge[top].st,edge[top].ed,edge[top].v);top++;}ans+=spfa(1);init();for(int i=0;i<top;i++)add(edge[i].ed,edge[i].st,edge[i].v);ans+=spfa(1);printf("%I64d\n",ans);}return 0;}