您的位置:首页 > 其它

HDU 1535 Invitation Cards(SPFA,及其优化)

2014-07-24 10:06 190 查看
题意:

有编号1~P的站点, 有Q条公交车路线,公交车路线只从一个起点站直接到达终点站,是单向的,每条路线有它自己的车费。

有P个人早上从1出发,他们要到达每一个公交站点, 然后到了晚上再返回点1。 求所有人来回的最小费用之和。

思路:

1.两次SPFA,也就是巧妙的将路线进行了翻转。

code 1:(数据较大,不能用二维数组,用的邻接表)

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 1000000
#define INF  0x3f3f3f3f
struct node
{
int now,to,w;
}edge[MAXN];//记录每条边的信息,起始点,终止点,权值
int first[MAXN],next[MAXN];
int dis[MAXN],vis[MAXN];
int n,m;
void turnup()//反转图
{
int i,k;
for(i = 0; i<=m; i++)
first[i] = next[i] = -1;
for(i = 0; i<m; i++)
{
k= edge[i].to;
next[i] = first[k];
first[k] = i;
}
}
void SPFA2(int start)
{
int i;
for(i = 0; i<=n; i++)
dis[i] = INF;
dis[start] = 0;
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(start);
while(!Q.empty())
{
start = Q.front();
Q.pop();
vis[start] = 0;
i = first[start];
while(1)
{
int to = edge[i].now;
if(dis[to]>dis[start]+edge[i].w)
{
dis[to]=dis[start]+edge[i].w;
if(!vis[to])
{
vis[to] = 1;
Q.push(to);
}
}
i = next[i];
if(i==-1)
break;
}
}
return;
}
void SPFA1(int start)
{
int i;
for(i = 0; i<=n; i++)
dis[i] = INF;
dis[start] = 0;
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(start);
while(!Q.empty())
{
start = Q.front();
Q.pop();
vis[start] = 0;
i=first[start];
while(1)
{
int to = edge[i].to;
if(dis[to]>dis[start]+edge[i].w)
{
dis[to]=dis[start]+edge[i].w;
if(!vis[to])
{
vis[to] = 1;
Q.push(to);
}
}
i = next[i];
if(i==-1)
break;
}
}
return;
}
int main()
{
int t,sum,i;
scanf("%d",&t);
while(t--)
{
sum = 0;
scanf("%d%d",&n,&m);
for(i=0; i<m; i++)
first[i]=next[i]=-1;
for(i=0; i<m; i++)
{
scanf("%d%d%d",&edge[i].now,&edge[i].to,&edge[i].w);
next[i]=first[edge[i].now];
first[edge[i].now]=i;
}
SPFA1(1);
for(i = 2; i<=n; i++)
sum+=dis[i];
turnup();
SPFA2(1);
for(i = 2; i<=n; i++)
sum+=dis[i];
printf("%d\n",sum);
}
return 0;
}


这里SPFA 可以优化,关于SPFA的优化:

SLF:Small Label First 策略。

  实现方法是,设队首元素为 i,队列中要加入节点 j,在 dj<=di 时加到队首而不是队尾,否则和普通的 SPFA 一样加到队尾。

LLL:Large Label Last 策略。

  实现方法是,设队列 Q 中的队首元素为 i,距离标号的平均值为 avg(d),每次出队时,若 di>avg(d),把 i 移到队列末尾,如此反复,直到找到一个 i 使 ,di<=avg(d)将其出队。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: