列表

详情


NC231895. 送快递

描述

Flash 是 A 城里的一位快递小哥,A 城中共有 家住户,门牌号依次为 ,它们通过 m 条双向道路相连。Flash 位于的快递站门牌号为 0,保证可以到达 A 城中的任意一家住户。

Flash 今天(第一天)接到了一个派送任务,需要向每一家住户派送一个神秘快递,但是 Flash 的能力有限,每天只能派送一件快递且只能从快递站出发。每一件快递都标明了一个截止日期,Flash 需要在第 i 个快递的截止日期 t_i 前将该快递送至门牌号为 i 的住户手中。例如,若在第 3 天,某个未被派送快递的截止日期为 3,当天派送它则可以成功送达,但如果同时有两个截止日期为 3 的未被派送的快递,那么 Flash 只能选择一个进行派送,另外一个必定超时。

对于每一件快递而言,其派送费等于最短派送路径的长度。但是,若某个快递超时,Flash 将会被处以相应派送费金额的罚款,并且不会得到任何派送费!

收益指总派送费减总罚款,请你帮忙计算出 Flash 此次任务的最大收益为多少?

输入描述

第一行输入两个整数 

接下来 m 行,每行输入三个整数 表示 u 号住户与 v 号住户之间有一条长度为 w 的道路。

行输入 n 个数 表示第 i 个快递的截止时间。

输出描述

输出一个整数,表示 Flash 的最大收益。

示例1

输入:

3 3
0 1 3
0 2 6
0 3 9
3 1 1

输出:

6

示例2

输入:

5 10
0 2 12
2 4 32
2 5 4
5 4 19
4 1 6
0 1 6
3 0 10
1 2 2
1 3 32
3 5 5
1 3 4 3 1

输出:

36

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 107ms, 内存消耗: 5616K, 提交时间: 2021-12-12 19:34:38

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=2e5+10;
#define x first
#define y second
int h[N],ne[M],e[M],idx,w[M];
int dis[N];
int n,m;
bool st[N];
typedef pair<int,int> PII;
PII a[N]; 
void add(int a,int b,int c)
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
void spfa()
{
	queue<int> q;
	q.push(0);
	memset(dis,0x3f,sizeof dis);
	dis[0]=0;
	st[0]=true; 
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		st[t]=false;
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dis[j]>dis[t]+w[i])
			{
				dis[j]=dis[t]+w[i];
				if(!st[j])
				{
				q.push(j);
				st[j]=true;
				}
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	while(m--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		add(a,b,c); 
		add(b,a,c);
	}
	spfa();
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x;
		a[i].y=dis[i];
	}
	sort(a+1,a+1+n);
	long long ans=0;
	priority_queue<long long,vector<long long >,greater<long long >> heap;
	for(int i=1;i<=n;i++)
	{
		if(a[i].x>heap.size())
		{
			ans+=a[i].y;
			heap.push(a[i].y);	
		}	
		else 
		{
			if(a[i].y>heap.top())
			{
				ans-=2*heap.top();
				heap.pop();
				heap.push(a[i].y);
			 	ans+=a[i].y;
			}
		}
		
	} 
	cout<<ans<<endl;
	return 0;
}

上一题