暑假-最短路(Bellman-ford、spfa)-E - Silver Cow Party

来源:互联网 发布:linux xampp 启动 编辑:程序博客网 时间:2024/05/16 05:33

题意:有n个牛场,m条(有向)路,举行派对的地点为第x个牛场

问:从每个牛场出发到举行派对的牛场再回到自己的牛场的最短时间里面的最大值

思路:SPFA算法,Dijkstra算法。

SPFA算法一次只能求一个顶点到其他各个顶点的最短路。所以要求n次,最后再判断

从n到x的最短路+从x到n的最短路的最大值即可。

优化:SPFA算法是求一个顶点到其他顶点的最短路,但是我们可以把先求一次从x出发到

其他顶点的最短路(回来的路),然后再把图逆转一次,在求一次从x到其他顶点的最短路

(来的路)。最后相加即可求出最大值。【同样可用于Dijkstra算法中】


SPFA:

#include<iostream>#include<cstring>#include<queue>using namespace std;const int MAXN = 1005;#define INF 0x3f3f3f3f//无穷大struct Node{int to;int val;Node *next;};Node *list[MAXN];//每个顶点的边链表表头指针int n, m, x;//顶点个数,边数,排队的地点int dist[MAXN][MAXN];//dist[i][j]:从i到j的最短距离int inq[MAXN];//每个顶点是否在队列中的标志void SPFA(int v0){queue<int>q;//队列中的结点为顶点序号Node *temp;for (int i = 1; i <= n; i++)//初始化{dist[v0][i] = INF;inq[i] = 0;}dist[v0][v0] = 0;inq[v0]++;q.push(v0);//起点入队列while (!q.empty())//不断地取出队列中的顶点松弛{int u = q.front();//u为队列头顶点序号q.pop();inq[u]--;temp = list[u];while (temp != NULL){if (dist[v0][temp->to] > dist[v0][u] + temp->val){dist[v0][temp->to] = dist[v0][u] + temp->val;if (!inq[temp->to]){q.push(temp->to);inq[temp->to]++;}}temp = temp->next;}}}int main(){int a, b, t,maxt=0;Node *temp;cin >> n >> m >> x;for (int i = 0; i < m; i++)//构造邻接表{temp = new Node;cin >> a >> b >> t;temp->to = b;temp->val = t;temp->next = NULL;if (list[a] == NULL){list[a] = temp;}else{temp->next = list[a];list[a] = temp;}}for (int i = 1; i <= n; i++){SPFA(i);//每次只能求顶点i到其他顶点的最短路}for (int i = 1; i <= n; i++)//求最长的来回时间{if (i == x){continue;}maxt = maxt > (dist[i][x] + dist[x][i]) ? maxt : (dist[i][x] + dist[x][i]);}cout << maxt << endl;return 0;}


优化,由原本的要求n次SPFA变成只需求2次SPFA

#include<iostream>#include<cstring>#include<queue>using namespace std;const int MAXN = 1005;#define INF 0x3f3f3f3fstruct Node{int to;int val;Node *next;};//邻接链表Node *list[MAXN];//顺序Node *relist[MAXN];//逆序【逆转之后的图】int n, m, x;//顶点数,边数,举行派对的地点int dist[MAXN], redist[MAXN];//点X到其他点的最短路【原来的图,回去的路】//其他点到X的最短路【逆转后的图,来路】void SPFA(int v0)//点X到其他点的最短路{queue<int>q;Node *temp;int inq[MAXN];for (int i = 1; i <= n; i++){dist[i] = INF;inq[i] = 0;}dist[v0] = 0;inq[v0]++;q.push(v0);while (!q.empty()){int u = q.front();q.pop();inq[u]--;temp = list[u];while (temp != NULL){if (dist[temp->to] > dist[u] + temp->val){dist[temp->to] = dist[u] + temp->val;if (!inq[temp->to]){q.push(temp->to);inq[temp->to]++;}}temp = temp->next;}}}void reSPFA(int v0)//其他点到X的最短路{queue<int>q;Node *temp;int inq[MAXN];for (int i = 1; i <= n; i++){redist[i] = INF;inq[i] = 0;}redist[v0] = 0;inq[v0]++;q.push(v0);while (!q.empty()){int u = q.front();q.pop();inq[u]--;temp = relist[u];while (temp != NULL){if (redist[temp->to] > redist[u] + temp->val){redist[temp->to] = redist[u] + temp->val;if (!inq[temp->to]){q.push(temp->to);inq[temp->to]++;}}temp = temp->next;}}}int main(){int a, b, t, maxt = 0;Node *temp;Node *retemp;cin >> n >> m >> x;for (int i = 0; i < m; i++){cin >> a >> b >> t;temp = new Node;temp->to = b;temp->val = t;temp->next = NULL;if (list[a] == NULL){list[a] = temp;}else{temp->next = list[a];list[a] = temp;}//构建原图【顺序】retemp = new Node;retemp->to = a;retemp->val = t;retemp->next = NULL;if (relist[b] == NULL){relist[b] = retemp;}else{retemp->next = relist[b];relist[b] = retemp;}//构造逆图【逆转后】}SPFA(x);reSPFA(x);for (int i = 1; i <= n; i++){if (i == x){continue;}maxt = maxt > (dist[i] + redist[i]) ? maxt : (dist[i] + redist[i]);//求来回最长的时间}cout << maxt << endl;return 0;}




0 0
原创粉丝点击