POJ 1511题
//题目类型:最短路类型
//算法实现:Dijkstra(邻接表+优先级队列) ,使用此算法效率非常高,只有2094MS
#include <stdio.h>
#include <iostream>
//#include <conio.h>
#include <queue>
using namespace std;
#define arraysize 1000001
#define maxData 1000000001
typedef unsigned long long u64_T;
typedef struct node
{
int v; //终点
u64_T w; //费用
node *next;
}node;
typedef struct pnode
{
int v;
u64_T length;
bool operator<(const pnode &temp) const
{
return length>temp.length;
}
}pnode;
node *adj[arraysize];
node *readj[arraysize];
node edges[arraysize]; //正向邻接表
node reedges[arraysize]; //逆向邻接表
bool final[arraysize];
u64_T d[arraysize];
int P,Q;
int edgenum,reedgenum;
void addEdge(int start,int end,u64_T w)
{
node *temp = &edges[edgenum++];
temp->v = end;
temp->w = w;
temp->next=adj[start];
adj[start] = temp;
}
void addReEdge(int start,int end,u64_T w)
{
node *temp = &reedges[reedgenum++];
temp->v = end;
temp->w = w;
temp->next = readj[start];
readj[start] = temp;
}
u64_T SPFA(int s,int flag) //使用flag区别是正向还是逆向
{
int i,j;
priority_queue<pnode> myqueue; //使用优先级队列实现
pnode frontnode,tempnode;
memset(final,0,sizeof(final)); //final用于标记该节点是否在队列中
for(i=1;i<P+1;++i) d[i] = maxData; //初始化:设置为无穷大
d[s] = 0; //源点的距离设置为0
final[s] = true;
frontnode.v = s;
frontnode.length = 0;
myqueue.push(frontnode);
while(!myqueue.empty()) //SPFA算法的终止条件,队列为空
{
int frontv = myqueue.top().v;
myqueue.pop();
final[frontv] = true;
node *nodep = NULL;
if(flag ==1)
nodep = adj[frontv];
else
nodep = readj[frontv];
for(;nodep;nodep=nodep->next) //对该点相邻的边进行松弛操作
{
int tempu = nodep->v;
u64_T templength = nodep->w;
if(!final[tempu] && d[tempu]>d[frontv]+templength)
{
d[tempu] = d[frontv]+templength;
tempnode.v = tempu;
tempnode.length = d[tempu];
myqueue.push(tempnode);
}
}
}
u64_T sum = 0;
for(i=1;i<=P;++i)
{
sum += d[i];
}
return sum;
}
int main()
{
//freopen("1.txt","r",stdin);
int N;
int i,j;
int start,end;
u64_T w;
scanf("%d",&N);
while(N--)
{
u64_T sum = 0;
edgenum = 0; //初始化边的数目
reedgenum = 0;
scanf("%d%d",&P,&Q);
for(i=1;i<=P;++i) //初始化邻接指针
{
adj[i] = NULL;
readj[i] = NULL;
}
for(i=1;i<=Q;++i)
{
scanf("%d%d%I64d",&start,&end,&w); //注意:读取unsigned long long 时,使用%I64d,不要使用%llu,若使用此此题读取出错。
addEdge(start,end,w);
addReEdge(end,start,w);
}
sum = SPFA(1,1)+SPFA(1,2);
printf("%llu\n",sum); //注:__int64的输出
}
//getch();
return 0;
}