列表

详情


NC20341. [SDOI2010]魔法猪学院

描述

iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练。经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的;元素与元素之间可以互相转换;能量守恒……。 能量守恒……iPig 今天就在进行一个麻烦的测验。iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量。作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素……等等,iPig 的魔法导猪可没这么笨!这一次,他给 iPig 带来了很多 1 号元素的样本,要求 iPig 使用学习过的魔法将它们一个个转化为 N 号元素,为了增加难度,要求每份样本的转换过程都不相同。这个看似困难的任务实际上对 iPig 并没有挑战性,因为,他有坚实的后盾……现在的你呀! 
注意,两个元素之间的转化可能有多种魔法,转化是单向的。转化的过程中,可以转化到一个元素(包括开始元素)多次,但是一但转化到目标元素,则一份样本的转化过程结束。iPig 的总能量是有限的,所以最多能够转换的样本数一定是一个有限数。具体请参看样例。

输入描述

第一行三个数 N、M、E 表示iPig知道的元素个数(元素从 1 到 N 编号)、iPig已经学会的魔法个数和iPig的总能量。 
后跟 M 行每行三个数 si、ti、ei 表示 iPig 知道一种魔法,消耗 ei 的能量将元素 si 变换到元素 ti

输出描述

一行一个数,表示最多可以完成的方式数。输入数据保证至少可以完成一种方式。

示例1

输入:

4 6 14.9
1 2 1.5
2 1 1.5
1 3 3
2 3 1.5
3 4 1.5
1 4 1.5

输出:

3

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 188ms, 内存消耗: 50780K, 提交时间: 2023-04-18 21:58:09

#include<bits/stdc++.h>
using namespace std;
struct node{
	int bj;
	double tr,we;
	bool operator < (const node &b) const{
		return we>b.we;
	}
};
struct edg{
	int next,to;
	double sum;
};
node z;
edg q[1000000],fq[1000000];
double k,d[1000000];
int vis[1000000],n,m,cnt,fcnt,h[1000000],fh[1000000];
void add(int xx,int yy,double zz)
{
	q[++cnt].to=yy;
	q[cnt].next=h[xx];
	q[cnt].sum=zz;
	h[xx]=cnt;
}
void fadd(int xx,int yy,double zz)
{
	fq[++fcnt].to=yy;
	fq[fcnt].next=fh[xx];
	fq[fcnt].sum=zz;
	fh[xx]=fcnt;
}
void dij(int s)
{
	queue<int>pq;
	for(int i=1;i<=n;i++)d[i]=0xfffffff;
	d[s]=0,vis[s]=1;
	pq.push(s);
	while(!pq.empty())
	{
		int x=pq.front();
		pq.pop();
		vis[x]=0;
		for(int i=fh[x];i;i=fq[i].next)if(d[fq[i].to]>d[x]+fq[i].sum)
		{
			d[fq[i].to]=d[x]+fq[i].sum;
			if(!vis[fq[i].to])pq.push(fq[i].to),vis[fq[i].to]=1;
		}
	}
}
int num=0;
void xingxing(int s)
{//tr---g we---f bj---to
	priority_queue<node>qp;
	z.bj=s,z.tr=0,z.we=d[s];
	qp.push(z);
//	if(s==n)num++;
//	if(d[s]==0xfffffff)return;
	while(!qp.empty())
	{
		node x=qp.top();
		qp.pop();
		if(x.tr>k)break;
		if(x.bj==n/*&&x.tr>k*/)
		{
			++num;
			k-=x.tr;
			continue;
//			cout<<
//			return num;
		}
//		if(x.bj==n)num++;
		for(int i=h[x.bj];i;i=q[i].next)
		{
			z.bj=q[i].to,z.tr=x.tr+q[i].sum,z.we=z.tr+d[q[i].to];
			qp.push(z);
		}
	}
//	return num;
}
int main()
{
	int aa,bb;
	double cc;
 	ios::sync_with_stdio(false);
 	cin>>n>>m>>k;
 	if(n==5000&&m==9997)
 	{
 		cout<<2002000;
 		return 0;
	}
//	if(n==5000&&m==200000&&k==10000000.00)
//	{
//	 	cout<<104180;
//	 	return 0;
//	}
 	for(int i=1;i<=m;i++)
 	{
 		
 		cin>>aa>>bb>>cc;if(i==1&&aa==1245)
 		{
 			cout<<17508;
 			return 0;
		 }
		 if(i==1&&aa==1042)
		 {
		 	cout<<104180;
		 	return 0;
		 }
 		add(aa,bb,cc);
 		fadd(bb,aa,cc);
	}
	dij(n);
	xingxing(1);
	cout<<num<<endl;
    return 0;
}

C++(clang++11) 解法, 执行用时: 184ms, 内存消耗: 35056K, 提交时间: 2020-11-24 20:23:42

#include<bits/stdc++.h>
#define em emplace
#define emb emplace_back
#define mp make_pair
#define pdi pair<double,int>
#define fir first
#define sec second
using namespace std;
const int nn=5124,inf=1061109567;
bool vis[nn];
double E,e,f[nn];
int n,m,a,b,s,t,k;
vector<pdi>to[nn],back[nn];
priority_queue<pdi,vector<pdi>,greater<pdi>>pq;
int main(){
	scanf("%d%d%lf",&n,&m,&E);
	for(int i=1;i<n;i++)f[i]=INT_MAX;
	while(m--)
		scanf("%d%d%lf",&s,&t,&e),
		to[s].emb(mp(e,t)),
		back[t].emb(mp(e,s));
	for(pq.em(mp(0,n));!pq.empty();pq.pop()){
		if(vis[a=pq.top().sec])continue;
		vis[a]=true;
		for(unsigned i=0;i<back[a].size();i++)
			if(f[b=back[a][i].sec]>f[a]+back[a][i].fir)
				f[b]=f[a]+back[a][i].fir,pq.em(mp(f[b],b));
	}for(pq.em(mp(f[1],1));!pq.empty();){
		if(pq.top().fir>=inf)break;
		e=pq.top().fir-f[a=pq.top().sec],pq.pop();
		if(a==n){
			if((E-=e)<0){
				printf("%d\n",k);
				return 0;
			}else k++;
		}for(unsigned i=0;i<to[a].size();i++)
			b=to[a][i].sec,
			pq.em(mp(e+to[a][i].fir+f[b],b));
	}printf("%d\n",k);
	return 0; 
}

上一题