POJ 1511 双向单源最短路 SPFA+邻接表
来源:互联网 发布:剑灵洪门崛起mac 编辑:程序博客网 时间:2024/05/22 08:16
最近在复习最短路算法
然后今天在看差分约束系统的时候看到了这一题 POJ 1511
题目的大意:
给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1)
题目意思很简单,但是数据规模很大,当时知道数据规模很大,用一般的方法肯定会超时或者其他错误,但是还是用基础的方法写了一遍。
还有就是一地方需要注意,就是这题求的是双向单源,所以还需要考虑一下,处理双向的问题很简单,逆向思维,求完第一遍之后,将存储的图方向调反,再SPFA(1)一次,然后两次的结果相加就是所求的答案了,这个逆向的思维很好。赶快找个本子记好。
第一次用的是 SPFA + 邻接矩阵 (然后死的很惨QAQ)
有需要注意的小地方就是这题给的编号是从1开始的,所以在建图的时候遍历就要从1开始,不然肯定是错的,而且错的你还很难找出来,早上花了很久在找这个问题,后来解决了。然后这题如果数据规模不是很大的话可以用SPFA+邻接矩阵来写,但是出题者给了10亿的数据 ,这就比较尴尬了。所以,比较好的方法就是用SPFA+邻接表
下面讲解一下SPFA+邻接表的算法:
#include <cstdio>#include <cmath>#include <climits>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define CLR(arr, what) memset(arr, what, sizeof(arr)) const int maxn = 1000010;const long long MAX = 10000000000000005;int head[maxn];int key[maxn];int next[maxn];int node[maxn];int num;int nodenum,edgenum;bool vis[maxn];long long dis[maxn];struct Edge{ int u; int v; int weight; }edge[maxn];void add(int u,int v,int cost){ key[num] = cost; next[num] = head[u]; node[num] = v; head[num] = num; num++;}void init(){ i = 0; CLR(head,-1); for(int i=1;i<=nodenum;i++){ dis[i] = MAX; }}long long SPFA(int start){ long long total = 0; int temp; queue<int> q; while(!q.empty()) q.pop(); CLR(vis,false); dis[start] = 0; vis[start] = true; q.push(start); while(!q.empty()){ temp = q.front(); q.pop(); vis[temp] = false; for(int i=head[temp];i!=-1;i=next[i]){ if(dis[node[i]]>dis[temp]+key[i]){ dis[node[i]] = dis[temp] + key[i]; if(!vis[node[i]]){ q.push(node[i]); vis[node[i]] = true; } } } } for(int i=1;i<=nodenum;i++) total += dis[i]; return total;}int main(int argc, char const *argv[]){ int T; int top; long long answer; scanf("%d",&T); while(T--){ top = answer = 0; scanf("%d%d",&nodenum,&edgenum); init(); for(int i=0;i<edgenum;i++){ scanf("%d%d%d",&edge[top].u,&edge[top].v,&edge[top].weight); add(edge[top].u,edge[top].v,edge[top].weight); top++; } answer+=SPFA(1); init(); for(int i=0;i<top;i++)//反置图 add(edge[i].v,edge[i].u,edge[i].weight); answer+=SPFA(1); printf("%lld\n",answer); } return 0;}
代码如上,其实对于邻接表不止一个方法建
还有用到指针的,这里是用head数组来更新下一个结点的序号来实现的
然后就是建立邻接表的时候大致有一个模子:
第一步:
typedef struct{ int to; int w; int next;}Edge;Edge e[MAX];int pre[MAX];//初始化memset(pre,-1,sizeof(pre));//输入scanf("%d %d %d",&from,&to,&w1);e[i].to = to; e[i].w = w1; e[i].next = pre[from]; pre[from] = i;i++;
第二步:
/now为弧尾结点序号,i为now所发出的边序号,adj为弧头结点序号,w为now–>adj这条边的权值/
for(i = pre[now]; i != -1; i = edge[i].next)
{
int adj = edge[i].to;
int w = edge[i].w;
//do something…
//做你想做的事情。
}
因为邻接表不是向邻接矩阵那样简单易懂所以可能理解起来会有点麻烦
多练应该会好一点吧 ,遇到最短路的时候先尝试用邻接表建立一下看看然后再慢慢找漏洞,相信会有一天可以弄精邻接表的。
好了 今天就到这里了 去吃饭喽 吃完饭继续刷题哦 :)
- POJ 1511 双向单源最短路 SPFA+邻接表
- POJ 1511(邻接表和最短路 SPFA)
- POJ 1511 邻接表+spfa
- poj 1511(SPFA+邻接表)
- 邻接表(spfa算法---单源最短路)
- 【图论】【单源最短路】【SPFA】pascal+邻接表
- poj 1511 Invitation Cards (SPFA、邻接表)
- Poj 1511- Invitation Cards(Spfa+邻接表)
- 邻接表和SPFA(POJ 1511)
- SPFA邻接表-POJ-1511-Invitation Cards
- poj 1511 Invitation Cards (spfa + 邻接表)
- SPFA单源最短路算法—vector模拟邻接表实现
- HDU 2544 最短路(spfa邻接表)
- SPFA求单源最短路(邻接表)
- poj Wormholes (最短路 spfa Bellman-Ford 算法 邻接表实现)
- poj 1511 Invitation Cards 静态邻接表的SPFA
- POJ 1511 Invitation Cards SPFA+正反邻接表
- poj 1511 Invitation Cards (spfa+邻接表)
- HFP cover art feature
- python代理脚本实现期望数据与实际数据的比对(V1.0)
- How does the lead number of inverse circular function be verified?
- Enable/Disable Multicast on Interface of a Linux Machine
- 合并链表和求1+2+...+n不用循环、乘除法、循环、条件判断、选择相关的关键字
- POJ 1511 双向单源最短路 SPFA+邻接表
- 用Kotlin开发android平台语音识别,语义理解应用(olamisdk)
- 基于Halcon12的图像拼接技术(按照Halcon例子改了一下)
- 常用的单行函数(oracle)
- 常用压力测试工具介绍
- ajax实现jsonp调用
- java初学者的浅谈2
- Shell脚本入门
- C++函数重载实现的原理以及为什么在C++中调用C语言编译的函数时要加上extern "C"声明