标签:
Time Limit: 8000MS | Memory Limit: 262144K | |
Total Submissions: 25219 | Accepted: 8346 |
Description
Input
Output
Sample Input
2 2 2 1 2 13 2 1 33 4 6 1 2 10 2 1 60 1 3 20 3 4 10 2 4 5 4 1 50
Sample Output
46 210
Source
原题链接:http://poj.org/problem?id=1511
参考博客:http://blog.csdn.net/wuyanyi/article/details/7286014
给定节点数n,和边数m,边是单向边.
问从1节点出发到2,3,...n 这些节点路程和从从这些节点回来到节点1的路程和最小值。
很显然的最短路,先以1为起点进行一次最短路,然后再将边反向一下再以1为起点进行一下最短路。
这题的意义在于数据,一般的dijstra的O(N^2)显然没法过。
dijstra+heap,其实heap直接用priority_queue实现即可
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int maxn=1000000+10; typedef long long LL ; const LL INF = 0x3f3f3f3f3f3f3f3f; int n,m; struct node { int to,next,w; } edge[maxn]; int head[maxn]; int a[maxn][3]; LL dis[maxn]; bool vis[maxn]; int cnt; void addEdge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void Init() { cnt=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); for(int i=0; i<=n; i++) dis[i]=INF; } LL spfa() { queue<int>q; q.push(1); vis[1]=true; dis[1]=0; while(!q.empty()) { int p = q.front(); q.pop(); vis[p] = false ; //注意spfa的vis和dijstra的不同点, //前者是判断是否在queue里而已 //后者是判断是否已经是最优的点。 for (int i=head[p]; i!=-1; i=edge[i].next) { int to = edge[i].to; int w = edge[i].w; if(dis[to]>dis[p]+w) { dis[to]=dis[p]+w; if(!vis[to]) { q.push(to); vis[to]=true; } } } } LL ans = 0; for (int i=1; i<=n; i++) { ans+=dis[i]; } return ans; } int main() { int T; //freopen("data/1511.txt","r",stdin); cin>>T; int x,y,z; while(T--) { cin>>n>>m; Init(); for(int i=0; i<m; i++) { scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]); addEdge(a[i][0],a[i][1],a[i][2]); } LL ans = spfa(); Init(); for(int i=0; i<m; i++) { addEdge(a[i][1],a[i][0],a[i][2]); } ans += spfa(); cout<<ans<<endl; } return 0; }
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <vector> using namespace std; const int maxn=1000000+10; typedef long long LL ; const LL INF = 0x3f3f3f3f3f3f3f3f; int n,m; struct node { int to,next,w; } edge[maxn]; int head[maxn]; int a[maxn][3]; LL dis[maxn]; bool vis[maxn]; int cnt; void addEdge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void Init() { cnt=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); for(int i=0; i<=n; i++) dis[i]=INF; } struct cmp { //注意priority_queue的cmp写的和sort里面的cmp的区别, //前者是struct,后者是函数, //而且比较大小的关系刚好是相反的。 bool operator() (const int a,const int b) { return dis[a]>dis[b]; } }; LL Dijkstra() { priority_queue<int,vector<int>,cmp>q; dis[1] = 0; q.push(1); while(!q.empty()) { int p = q.top(); q.pop(); vis[p] = true; for(int i=head[p]; i!=-1; i=edge[i].next) { int to=edge[i].to; int w=edge[i].w; //如果是可松弛点即加入优先队列,dis值越小越优先。 if(!vis[to]&&dis[to]>dis[p]+w) { dis[to]=dis[p]+w; q.push(to); } } } LL ans = 0; for(int i=1; i<=n; i++) ans+=dis[i]; return ans; } int main() { int T; //freopen("data/1511.txt","r",stdin); cin>>T; int x,y,z; while(T--) { cin>>n>>m; Init(); for(int i=0; i<m; i++) { scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]); addEdge(a[i][0],a[i][1],a[i][2]); } LL ans = Dijkstra(); Init(); for(int i=0; i<m; i++) { addEdge(a[i][1],a[i][0],a[i][2]); } ans += Dijkstra(); cout<<ans<<endl; } return 0; }
POJ 1511 Invitation Cards 【最短路,spfa算法,Dijkstra算法堆优化】
标签:
原文地址:http://blog.csdn.net/hurmishine/article/details/52211178