题目地址:http://poj.org/problem?id=1511
方法一:
/* 本题使用邻接表采用动态开辟的方式保存所有的边,首先定义一个保存指向的顶点和边所对应权值, */ #include<cstdio> #include<cstring> #include<queue> using namespace std; #define NMAX_D 1000005 #define NMAX 1000000001 int n,m; //定义结构体 struct node { int v,cost; node *next; }edge[NMAX_D],redge[NMAX_D];//定义两个数组,edge用来保存顺向边,redge保存逆向边 bool vis[NMAX_D];//标记数组,用来标记结点i是否已经在队列里面,防止重复对同一节点进行扩展 int dis[NMAX_D];//保存起点到目标结点的距离 __int64 sum;//用来保存总的费用,显然最后结果很可能超int queue<int> Q; void release(node edge[])//初始化结点,分离出所有结点 { node *p,*q; for(int i = 1; i <= n; i++) { p = &edge[i]; while(p->next) { q = p->next; p->next = q->next; free(q); } } } void init()//输入各边关系和边所对应的权值。并构造邻接表 { int a,b,c; node *p,*q; release(edge); release(redge); for(int i = 0; i < m;i++ ) { scanf("%d%d%d",&a,&b,&c); q = (node*)malloc(sizeof(node)); q->v = b; q->cost = c; p = &edge[a]; q->next = p->next; p->next = q; q = (node*)malloc(sizeof(node)); q->v = a;q->cost = c; p = &redge[b]; q->next = p->next; p->next = q; } } //spfa算法,求最短路径 void psfa(node edge[]) { int i; //初始化数组vis和数组dis memset(vis,false,sizeof(vis)); for(i = 0; i <= n; i++) dis[i] = NMAX; dis[1] = 0; vis[1] = true;//标记1号结点已经在队列中 Q.push(1);//第一个顶点进队列 while( !Q.empty()) { int now = Q.front();//取队头元素 Q.pop();//队头元素出队列 vis[now] = false;//标记now结点为不在队列中 for(node *p = edge[now].next; p ; p = p->next) { if(dis[p->v] > dis[now] + p->cost)//求当存在大结点p->v更短的路径时,更新从起点到p->v的路径 { dis[p->v] = dis[now] + p->cost; if(!vis[p->v])//当结点p->v已经在队列中则不再进队列 { vis[p->v] = true; Q.push(p->v); } } } } for(i = 1; i <= n; i++)sum += dis[i]; } int main() { int t; scanf("%d",&t); while( t-- ) { scanf("%d%d",&n,&m); init(); sum = 0; psfa(edge); psfa(redge); printf("%I64d\n",sum); } return 0; }
方法二:
用SPFA,又加了点优化用SLF。
/* 采用邻接表的变形版本保存,用两个指针数组保存结点,用一个连续的一维数组保存边, 起于同一顶点的边用指针连接。 */ #include<stdio.h> #include<string.h> #include<deque> using std::deque; #define INF (1<<30) #define MAXN 1000001 //用来保存数据的结构体 struct node { int v,cost; node *next; }; //*head1[]和*head[]均为保存结点的指针数组,edge,和redge两个数组用来保存 node *head1[MAXN],*head[MAXN],edge[MAXN],redge[MAXN],*p1,*q1; int n,m,dis[MAXN]; bool vis[MAXN]; deque<int>Q; __int64 sum; void init() { int i,a,b,c; p1 = edge,q1 = redge,sum = 0; for(i = 0; i <= n; i++)head1[i] = head[i] = NULL; for(i = 0; i < m; i++) { scanf("%d%d%d",&a,&b,&c); p1->v = b;p1->cost = c; p1->next = head[a]; head[a] = p1++; q1->v = a;q1->cost = c; q1->next = head1[b]; head1[b] = q1++; } } void spfa(bool is) { int i ; memset(vis,false,sizeof(vis)); for(i = 2; i <= n; i++)dis[i] = INF; dis[1] = 0; vis[1] = true; Q.push_front(1); while( !Q.empty() ) { int now = Q.front(); Q.pop_front(); vis[now] = false; for(p1 = (is) ? head[now] : head1[now] ; p1; p1 = p1->next) { if(dis[p1->v] > dis[now] +p1->cost) { dis[p1->v] = dis[now] + p1->cost; //p1->v进队列 if( !Q.empty() && dis[p1->v] < dis[Q.front()]) Q.push_front(p1->v); else Q.push_back(p1->v); vis[p1->v] = true; } } } for(i = 1; i <= n; i++)sum += dis[i]; } int main() { int t; scanf("%d",&t); while( t-- ) { scanf("%d%d",&n,&m); init(); spfa(true); spfa(false); printf("%I64d\n",sum); } return 0; }