浙江省第13届省赛K题
题意:要修建m条路,修每条路花费Ci dollars,经过这条路需要Di分钟,求从0结点到其他n-1个节点的时间最小且修路花费最小。
思路:从0结点开始往外拓展,把与其相关的点加入队列里面,找到从0能到达的时间最短的点a,标记了,再把与其相关的未访问的结点加入队列,,其时间要加上到达a的时间,这样继续下去,其实就是每次找已标记的点所能到达的最近的点并将其标记,直到把所有点标记。
详细见代码:
#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
typedef unsigned long long LLu;
typedef long long LL;
const int maxn=2*1e5+100;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MOD = 1e9+7;
struct node
{
int to;
LL t,c;
};
bool operator < (node a,node b)
{
return a.t<b.t||(a.t==b.t&&a.c<b.c);
}
int head[maxn];
bool vis[maxn];
int Next[maxn];
node info[maxn];
int tot;
void init()
{
memset(head,-1,sizeof head);
memset(vis,true,sizeof vis);
tot=0;
}
void add(LL fr,LL to,LL t,LL c)
{
Next[tot]=head[fr];
info[tot].to=to;
info[tot].t=t;
info[tot].c=c;
head[fr]=tot++;
}
priority_queue<node >q;
void bfs()
{
vis[0]=false;
LL time=0;LL doll=0;
int i;
for( i=head[0];i!=-1;i=Next[i])
{
node b=info[i];
b.t=-b.t;
b.c=-b.c;
q.push(b);
}
while(!q.empty())
{
node a=q.top();
q.pop();
// printf("%d \n",a.to);
if(!vis[a.to]) continue;
vis[a.to]=false;
time=time+a.t;
doll=doll+a.c;
for(i=head[a.to];i!=-1;i=Next[i])
{
node b=info[i];
if(!vis[b.to]) continue;
b.t=-b.t+a.t;
b.c=-b.c;
q.push(b);
// printf("%d df\n",b.to);
}
}
printf("%lld %lld\n",-time,-doll);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
int i,j,k;
LL x,y,d,c;
init();
for(i=1;i<=m;i++)
{
scanf("%lld%lld%lld%lld",&x,&y,&d,&c);
add(x,y,d,c);
add(y,x,d,c);
}
// cout<<m<<endl;
bfs();
}
return 0;
}