浙江省第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;
}