下面是我编写的代码,SPFA算法的时间复杂度比较优越。需要用到一个队列,但不同的是,元素入队后可能会再次入队。
SPFA算法用队列来保存可能做松弛操作的节点。
初始时所有点d[]值置INF,源点d[s]为0。将源点放进队列。
当队列不为空时每次从队列中取出队首节点,对该节点发出的每条边进行松弛。将松弛后d[]值改变并且不在队列中的点加入队列。
1.首先初始化 2然后每次取对头元素进行松弛3若产生作用端点不在队列中则加入队列。
vis的作用是用来存储对象是否在队列之中的
本题是一个单行道有向图的(虽说道路一般都是无向的)
/*这个题目点的数量可以达到100000 而边的数量最多不过100000
属于稀疏矩阵,并且如果采用矩阵存储的话会超内存,并且O(n^2)
的时间复杂度也是伤不起的,采用前向星存储以节省空间
采用spfa算法来节省时间O(ke),题目思路用逆向思维,
求每个人到第一个人的最短路之和
其实就是求第一个人到每个人的单源最短路径之和(是一个无向图)*/
#include<cstdio>
#include<vector>
#include<queue>
#define MAXN 100005
using namespace std;
struct edge
{
int start,end;
int val;
};
int n,m,i,j,a,b,w;
vector<edge> v[MAXN];
int dis[MAXN];
bool visited[MAXN];
void spfa()
{
for(i=1;i<=n;i++)
{
dis[i] = MAXN;
visited[i] = false;
}
queue<int>Q;
dis[1] = 0; //没问题的 这里已经设置为0
Q.push(1);
while(!Q.empty())
{
int temp = Q.front();
Q.pop();
for(unsigned i=0;i<v[temp].size();i++)
{
if(dis[temp] + v[temp][i].val < dis[v[temp][i].end])
{
dis[v[temp][i].end] = dis[temp] + v[temp][i].val;
if(visited[v[temp][i].end]==false)
{
Q.push(v[temp][i].end);
visited[v[temp][i].end]= true;
}
}
}
visited[temp] = false;
}
}
int main()
{
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&n,&m)==2)
{
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&w);
edge temp;
temp.start = b;
temp.end = a;
temp.val = w;
v[b].push_back(temp);
}
spfa();
int sum = 0;
for(i=2;i<=n;i++)
{
sum+=dis[i];
}
printf("%d\n",sum);
}
return 0;
}
聚会
party.pas/c/cpp
1s/64MB
【题目描述】
n个人打算一起聚会,聚会的地点定在第一个人家里,现在除了第一个人已经在家之外其他人都不在第一个人家里,求n个人到第一个人家里的最短路径长度总和。
【输入】
输入第一行包含两个数n, m,表示人数和以及连通这个n人所在位置的道路数。
接下来的m行每行有3个数ai, bi, wi,表示第i条道路是从第ai个人所在位置指向第bi个人所在位置的单行道,长度为wi。
【输出】
输出一个整数,n个人的最短路径总长度。
【输出样例】
4 4
2 1 1
3 1 2
4 3 2
3 4 1
【输出样例】
7
【数据规模】
对于第0-3组测试数据,n<=100,m<=150
对于第4-7组测试数据,n<=1000,m<=1500
对于第8-9组测试数据,n<=100000,m<=100000
完成情况(cena测评)
这一题虽说是从各个点到一个点,但是我们可以反过来想一下,我们把所有的边都反向,然后求从1到所有点的最短路就和原问题一样了
C++ AC Code
- /*http://blog.csdn.net/jiangzh7
- By Jiangzh*/
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<utility>
- using namespace std;
- const int N=100000+10;
- int n,m;
- struct link{int y,z;link *next;}*head[N];
- typedef pair<int,int> pii;
- priority_queue<pii> Q;
- int dist[N];
- bool h[N];
- void inlink(int x,int y,int z)
- {
- link *node=new link;
- node->y=y;node->z=z;
- node->next=head[x];
- head[x]=node;
- }
- void read()
- {
- freopen("party.in","r",stdin);
- freopen("party.out","w",stdout);
- scanf("%d%d",&n,&m);
- for(int i=1;i<=m;i++)
- {
- int x,y,z;
- scanf("%d%d%d",&x,&y,&z);
- inlink(y,x,z);
- }
- }
- void work()
- {
- memset(dist,0x3f,sizeof(dist));
- dist[1]=0;Q.push(make_pair(0,1));
- while(!Q.empty())
- {
- pii u=Q.top();Q.pop();
- int k=u.second;
- if(h[k]) continue;
- h[k]=true;
- for(link *node=head[k];node;node=node->next)
- if(dist[node->y]>dist[k]+node->z)
- {
- dist[node->y]=dist[k]+node->z;
- Q.push(make_pair(-dist[node->y],node->y));
- }
- }
- int res=0;
- for(int i=1;i<=n;i++) res+=dist[i];
- printf("%d\n",res);
- }
- int main()
- {
- read();
- work();
- return 0;
- }