#洛谷 通往奥格瑞玛的道路

移步到新Blog获得更好的代码阅读体验




看了很长时间才看懂这是一个最大值最小问题 果断二分答案。

主要思想是先跑一边Bellman-Ford+队列优化(也叫SPFA)把二分值设定成+∞ 然后看一看如果到终点的花费大于血量就输出AFK(away from keyboard)

如果可行就快排点权+二分下标 如果当前二分值可以跑到终点(跑SPFA判)就向左找(升序sort),不然就向右找。

跑SPFA的时候传一个upat也就是二分值 把点权大于二分值的点都判(删)掉 


还有一点就是最后还要判一下二分值。链式前向星+SPFA+手写Sort没有注释……

#include
#include
#include
#include
using namespace std;

//GRAPH
struct eg
{
	int pre,to;
	long long w;
};
eg edge[100010]={0};//linked stars
int pointer[10010]={0},edgenum,nodenum,fx,tx; long long wx;//info
int moneyp[10010]={0}; long long moneyx[10010]={0},blood; //node weight & conditions
//ALGORITHMS
long long dis[10010]; int que[70010],head,tail,prex,cache1;//spfa
int leftx,rightx,midx;//dichotomy
bool init[10010],cango[10010];//in the queue & can be visited

//AddEdge
void Insert(int at,int fromx,int tox,long long weix)
{
	edge[at].pre=pointer[fromx];
	edge[at].to=tox;
	edge[at].w=weix;
	pointer[fromx]=at;
	return;
}
//Quick Sort
void QSort(int l,int r)
{
	int mid=moneyx[(l+r)/2],i=l,j=r,x1,x2;
	while (i<=j)
	{
		while (moneyx[i]mid) j--;
		if (i<=j)
		{
			x1=moneyx[i]; moneyx[i]=moneyx[j]; moneyx[j]=x1;
			x2=moneyp[i]; moneyp[i]=moneyp[j]; moneyp[j]=x2;
			i++; j--;
		}
	}
	if (iupat) cango[moneyp[i]]=true;
	que[head]=1; init[1]=true; dis[1]=0;
	while (head<=tail)
	{
		cache1=que[head]; head++; init[cache1]=false;
		prex=pointer[cache1];
		while (prex>0)
		{
			if (dis[edge[prex].to]>dis[cache1]+edge[prex].w && cango[edge[prex].to]==false)
			{
				dis[edge[prex].to]=dis[cache1]+edge[prex].w;
				tail++; que[tail]=edge[prex].to;
				init[edge[prex].to]=true;
			}
			prex=edge[prex].pre;
		}
	}
	if (dis[nodenum]<=blood) return true;
	else return false;
}

int main()
{
	memset(dis,0x3f,sizeof(dis));
	memset(moneyx,0x3f,sizeof(moneyx));
	scanf("%d%d%lld",&nodenum,&edgenum,&blood);
//Input Money
	for (int i=1;i<=nodenum;i++) { scanf("%lld",&moneyx[i]); moneyp[i]=i; }
	QSort(1,nodenum);
//Input Edges
	for (int i=1;i<=edgenum*2;i+=2)
	{
		scanf("%d%d%lld",&fx,&tx,&wx);
		Insert(i,fx,tx,wx);
		Insert(i+1,tx,fx,wx);
	}
//Dichotomy & get the answer
	leftx=1; rightx=nodenum; midx=(leftx+rightx)/2;
	if (spfa(1000000010)==false)
	{
		printf("AFK\n");
		return 0;
	}
	else while (leftx<=rightx)
	{
		if (spfa(moneyx[midx])==true)
		{
			rightx=midx-1;
			midx=(leftx+rightx)/2;
		}
		else
		{
			leftx=midx+1;
			midx=(leftx+rightx)/2;
		}
	}
	if (spfa(moneyx[leftx])==true) printf("%lld",moneyx[leftx]);
	return 0;
}

你可能感兴趣的:(#洛谷 通往奥格瑞玛的道路)