-
时间: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;
}
时间: 2024-10-28 19:25:02