POJ1511 Invitation Cards(SPFA+逆图)

来源:互联网 发布:加入淘宝教育 编辑:程序博客网 时间:2024/05/21 20:22

链接:http://poj.org/problem?id=1511

题意:

求从1出发到每个点,再从每个点出发到1的最短路

从1到每个点的最短路,用一次spfa就能求出来了,但是从每个点到1的就很难求

所以存了两幅图,一副是正常方向的图,一副是相反的逆图,再从1出发,求一次逆图的最短路

就可以求出从每个点到1的距离了


而且,因为这题数据比较大,所以我原本准备用vector来存边,结果会超时,所以从其他博客中学习,改用链表的形式来存边,能节省很多空间和时间

非常好的方法


代码:

#include<cstdio>#include<algorithm>#include<iostream>#include<string>#include<cstring>#include<cstdlib>#include<cmath>#include<set>#include<map>#include<vector>#include<queue>#include<ctime>using namespace std;const int INF = 1e9 + 9;const int MAXN = 1000000 + 10;int n, m;struct node{int to, l;int next;}edge[2][MAXN];//0是正向图,1是逆向图bool vis[MAXN];int d[MAXN];int tol[2];int head[2][MAXN];void addedge(int s, int e, int l, int k)//用k标记是正图还是逆图{int &tot = tol[k];edge[k][tot].to = e;edge[k][tot].l = l;edge[k][tot].next = head[k][s];head[k][s] = tot++;}void Spfa(int st, int k){int i;for (i = 1; i <= n; i++){d[i] = INF;vis[i] = false;}d[st] = 0;vis[st] = true;queue<int> Q;Q.push(st);while (!Q.empty()){int start = Q.front();Q.pop();vis[start] = false;for (i = head[k][start]; i != -1; i = edge[k][i].next){if (d[start] + edge[k][i].l < d[edge[k][i].to]){d[edge[k][i].to] = d[start] + edge[k][i].l;if (!vis[edge[k][i].to]){vis[edge[k][i].to] = true;Q.push(edge[k][i].to);}}}}}int main(){//  freopen("D://input.txt", "r", stdin);//  freopen("D://output.txt", "w", stdout);int T;scanf("%d", &T);while (T--){memset(head, -1, sizeof(head));tol[0] = tol[1] = 0;//边数初始化为0int i;scanf("%d%d", &n, &m);for (i = 0; i < m; i++){int x, y, z;scanf("%d%d%d", &x, &y, &z);addedge(x, y, z, 0);addedge(y, x, z, 1);}__int64 sum = 0;Spfa(1, 0);for (i = 1; i <= n; i++){sum += d[i];}Spfa(1, 1);//两次spfafor (i = 1; i <= n; i++){sum += d[i];}printf("%I64d\n", sum);}//  printf("\n%.3lf\n",clock()/CLOCKS_PER_SEC);return 0;}



0 0
原创粉丝点击