移步到新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;
}