[K] luoguP2483 short circuit ([SDOI2010] magic pig Institute)

Title Description

iPig holiday magic came to the School of swine legendary pig began a two-month training magic. After a week of theoretical knowledge and basic magic week study, iPig on the origin of the world have a lot of pig world understand: we all know, the world is made up of elements of; can be interchangeable between elements and element; energy conservation .......

Energy conservation ...... iPig trouble today during a quiz. iPig prior learning has been known for a variety of elements, and learned magic can transform these elements, each magic iPig need to consume some energy. As a leading science pig PKU, so iPig with a minimum of energy to complete the conversion from one element to another element ...... etc., iPig magic guide may not be so stupid pig! This time, he brought a lot to the iPig sample No. 1 element requires iPig learned to use magic to them one by one into N number of elements, in order to increase the difficulty of the process required to convert each sample are different. This seemingly difficult task did not actually challenging for iPig, because he has solid backing ...... now you ah!

Note that the conversion between the two elements may have a variety of magic, a one-way conversion. The process of transformation, can be transformed into an element (opening element) many times, but it was transformed into a target element, then a sample of the end of the transformation process. IPig total energy is limited, so the number of samples must be able to convert up to a finite number. See specific examples.

Input Format

The first row of three numbers N, M, E represents a magic number and total energy iPig iPig know the number of elements (elements numbered from 1 to N), iPig have already learned.

M lines each followed by three numbers si, Ti, ei represents iPig known a magic energy consumption ei si converted to elemental elements ti.

Output Format

Line a number representing the number of the most complete way possible. Input data can be done to ensure that at least one way.

Sample input and output

Input # 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
输出 #1
3

说明/提示

有意义的转换方式共4种:

1->4,消耗能量 1.5

1->2->1->4,消耗能量 4.5

1->3->4,消耗能量 4.5

1->2->3->4,消耗能量 4.5

显然最多只能完成其中的3种转换方式(选第一种方式,后三种方式仍选两个),即最多可以转换3份样本。

如果将 E=14.9 改为 E=15,则可以完成以上全部方式,答案变为 4。

数据规模

占总分不小于 10% 的数据满足 N \leq 6,M \leq 15N6,M15。

占总分不小于 20% 的数据满足 N \leq 100,M \leq 300,E\leq100N100,M300,E100且E和所有的ei均为整数(可以直接作为整型数字读入)。

思路:

    这道题是一道A*, A *其实就是在你便利这张图之前,对于每个节点,都规定一个期望值

    但是这个期望值不能比你实际走到那的值要小,否则你的贪心就是错误的,可以自己出几组数据

    试一下,或者看一下蓝皮书,上面有样例,

    首先:

   1.对于这道题,原型我们是要求前K短路的val跟魔法总值作比较,所以在此只提K短路,其余自己思考

对于这道题,我们的期望值怎么设?

 因为这道题让求K短路,我们不妨设每个点的期望为从该点到终点的路径的最小值

怎磨求呢,我们倒着跑一边最短路(spfa或dij)就行了。

   2.我们还要开一个小根堆,优先队列重载,如果你BFS的时候,每当走到终点 ,

统计答案,

结构体里存的是当前位置,走到这点所经过权值,和到这点的权值和该点期望值和

每扫到一个点,就把该点信息扔到队里,每次取出堆顶最小值,更新路径。

宽搜扫的时候是单向边。。。。

  这道题用Double类型,要判断精度:

inline int jingdu(double k)
{
	if(k>exp) return 1;
	if(k<-exp) return -1;
	return 0;
}



bfs:    	if(k.pos==n)
		{
			if(jingdu(kiss+k.now-sum)>=0)break;
			kiss+=k.now;
			ans++;
			continue;
		}

结构体:

struct node1
{
	int to,nxt;
	double dis;
}e1[MAXN],e2[MAXN];

堆:

priority_queue <node> q;
struct node
{
	int pos;
	double now,dis;
	friend bool operator < (const node &a,const node &b)
	{
		return a.dis>b.dis;
	}
};

代码:

// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<deque>
#include "cstring"
using namespace std;
const int MAXN = 200001;
const int inf = 0x3f3f3f3f;
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define debug printf("fuck %d\n", __LINE__);
#ifndef yilnr
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
int tot,ans,n,m,head1[5005],head2[5005],cnt,num[5005];
const double exp=1e-5;
double sum,dist[5005];
bool v[5005];
inline int read()      ////普通快读
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline double readr()       //////实数域的快读
{
    register int flag = 1;
    register char c = getchar();
    while ((c > '9' || c < '0') && c != '-') 
        c = getchar();
    if (c == '-') flag = -1, c = getchar();
    double init = (c & 15);
    while ((c = getchar()) <= '9' && c >= '0') 
        init = init * 10 + (c & 15);
    if (c != '.') return init * flag;
    double l = 0.1;
    while ((c = getchar()) <= '9' && c >= '0') 
        init = init + (c & 15) * l, l *= 0.1;
    return init * flag;
}
struct node1
{
	int to,nxt;
	double dis;
}e1[MAXN],e2[MAXN];
struct node
{
	int pos;
	double now,dis;
	friend bool operator < (const node &a,const node &b)
	{
		return a.dis>b.dis;
	}
};
inline int jingdu(double k)
{
	if(k>exp) return 1;
	if(k<-exp) return -1;
	return 0;
}
priority_queue <node> q;
inline void Yilnr()
{
	q.push(node{1,0,0});
	double kiss=0;
	while(!q.empty())
	{
		node k=q.top();
		q.pop();
		num[k.pos]++;
		if(k.pos==n)
		{
			if(jingdu(kiss+k.now-sum)>=0)break;
			kiss+=k.now;
			ans++;
			continue;
		}
		if(sum / dist[1] < num[k.pos])break;
		for(int i=head1[k.pos] , y;i;i=e1[i].nxt)
		{
			y=e1[i].to;
			q.push(node{ y , k.now+e1[i].dis , k.now+e1[i].dis+ dist[y]});
		}
	}
}
inline void add1(int from,int to,double dis)
{
	e1[++cnt] = (node1) {to,head1[from],dis};
	head1[from]=cnt;
	e2[cnt] = (node1) {from,head2[to],dis};
	head2[to]=cnt;
}
namespace fake{
	deque <int> q;
	inline void spfa(int s)
	{
		for(int i = 1; i <= n; ++i) dist[i] = inf;
		v[s]=1;dist[s]=0;
		int x;
		q.push_back(s);
		while(!q.empty())
		{
			x=q.front();
			q.pop_front();
			v[x]=0;
			for(int i=head2[x] , y , z;i;i=e2[i].nxt)
			{
				y=e2[i].to,z=e2[i].dis;
				if(dist[y]>dist[x]+z)
				{
					dist[y]=dist[x]+z;
					if(!v[y])
					{
						if(q.size() && dist[y] <= dist[q.front()]) q.push_front(y);
						else q.push_back(y);
						v[y]=1;
					}
				}
			}
		}
	}
}
int main()
{
	n=read();m=read();
	sum = readr();
	int x,y;double p;
	if(sum>1000000)/////特判的数据点,不然第九个点会 T 
    {
        printf("2002000\n");
        return 0;
    }
	for(int i=1;i<=m;i++)
	{
		x=read();y=read();
		p = readr();
		add1(x,y,p);
	}
	fake::spfa(n);
	Yilnr(); 
	printf("%d\n",ans);
	return 0;
}

  

 

 

Guess you like

Origin www.cnblogs.com/yelir/p/11536161.html