时间:2016-04-05 12:57:22 星期二
题目编号:[2016-04-05][POJ][1511][Invitation Cards]
题目大意:给定一个有向图,从点1出发,分别到各个站点后,又回到点1,问最少需要多少车费,
分析:
- 从1跑一次最短路,然后矩阵转置,再跑一次最短路,两次求和
- 这里不能用邻接矩阵保存,所以改成邻接表,然后矩阵转置的操作变成重新加一次边
遇到的问题:用vector存图超时,改用数组实现
#include <queue>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;typedef long long ll;const int maxn = 1E6 + 20;const int maxm = 1E6 + 20;int head[maxn],nxt[maxm],mend[maxm],cost[maxm];void addedge(int u,int v, int c){ static int q = 2; mend[q] = v; nxt[q] = head[u]; cost[q] = c; head[u] = q++; }struct Edge{ int u,v,c; Edge(int _u = 0, int _v = 0,int _c = 0):u(_u),v(_v),c(_c){}}e[maxn];struct mNode{ ll u,c; mNode(ll _u = 0,ll _c = 0):u(_u),c(_c){} bool operator < (const mNode & a)const{ return c > a.c; }};bool vis[maxn];ll d[maxn];ll Dijkstra(int s,int n){ memset(vis,0,sizeof(bool) * (n + 2)); memset(d,0x3f,sizeof(ll) * (n + 2)); priority_queue<mNode> q; d[s] = 0; q.push(mNode(s,0)); mNode tmp; while(!q.empty()){ tmp = q.top(); q.pop(); int u = tmp.u; if(vis[u]) continue; vis[u] = 1; for(int qq = head[u];~qq;qq = nxt[qq]){ int v = mend[qq]; if(!vis[v] && d[v] > d[u] + cost[qq]){ d[v] = d[u] + cost[qq]; q.push(mNode(v,d[v])); } } } ll ans = 0; for(int i = 2; i <= n ; ++i) ans += d[i]; return ans;}inline void ini(int n){ memset(head,-1,sizeof(int)*(n + 2));}int main(){ int t,n,m,a,b,c; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); ini(n); for(int i = 0;i < m ; ++i){ scanf("%d%d%d",&a,&b,&c); e[i] = Edge(a,b,c); addedge(a,b,c); } ll ans; ans = Dijkstra(1,n); ini(n); for(int i = 0;i < m ; ++i){ addedge(e[i].v,e[i].u,e[i].c); } ans += Dijkstra(1,n); printf("%I64d\n",ans); } return 0;}