zoj3946 Highway Project
题意:n个城市,m条边,从编号为0的城市开始,到1~n-1标号的城市的最短路径合,及建这些路所需的最少资金。(路短考虑优先)
注:n 的大小在10^5内,那么我所学的基本的Dijkstra算法的模板就要 T 了,而且如果要开二维的数组,这也太大,开不了。
我的解决方案:一开始并没有考虑超不超时,所以就想如何解决开数组的问题,然后就想到了用优先队列,但写完之后果断TLE,想改,但比赛就结束了,写这个代码用了一个小时,还是弱爆了,对题目的思路与时间概念的敏感性也不够。之后的之后就是比赛后的补题,写时还需学长的提醒,真是伤心。
思路:还是优先队列,然后类似广搜的方法,有点像贪心一样来解决这个问题,但是主思想还是Dijkstra算法~~
我的代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#define LL long long
#define Inf 1e12
using namespace std;
struct node
{
int to;
LL tt;
LL mm;
node(){}
node(int to, LL tt, LL mm):to(to), tt(tt), mm(mm){}
friend bool operator < (node a, node b)
{
if(a.tt == b.tt)
return a.mm > b.mm;
return a.tt > b.tt;
}
}tem;
vector<node> q[110000];
priority_queue<node> v;
LL dis[110000], cost[110000];
int vis[110000];
void init(int sp)
{
for(int i = 0; i < sp; i++)
{
dis[i] = Inf;
vis[i] = 0;
cost[i] = Inf;
q[i].clear();
}
while(!v.empty()) v.pop();
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int sp, road, from, to;
LL t, m;
scanf("%d%d", &sp, &road);
init(sp);
for(int i = 0; i < road; i++)
{
scanf("%d%d%lld%lld", &from, &to, &t, &m);
q[from].push_back(node(to, t, m));
q[to].push_back(node(from, t, m));
}
v.push(node(0, 0, 0));
dis[0] = 0;
cost[0] = 0;
while(!v.empty())
{
tem = v.top();
v.pop();
if(vis[tem.to]) continue;
vis[tem.to] = 1;
for(int i = 0; i < q[tem.to].size(); i++)
{
node p = q[tem.to][i];
if(dis[p.to] > dis[tem.to] + p.tt)
{
dis[p.to] = dis[tem.to] + p.tt;
cost[p.to] = p.mm;
v.push(node(p.to, dis[p.to], cost[p.to]));
}
else
{
if(dis[p.to] == dis[tem.to] + p.tt && cost[p.to] > p.mm)
{
cost[p.to] = p.mm;
v.push(node(p.to, dis[p.to], cost[p.to]));
}
}
}
}
LL ans1 = 0, ans2 = 0;
for(int i = 1; i < sp; i++)
{
ans1 += dis[i];
ans2 += cost[i];
}
printf("%lld %lld\n", ans1, ans2);
}
return 0;
}
若有错,请大家多多指教~~~