题目大意:给定一个值E 求起点到终点的最多条路径 使长度之和不超过E
k短路的A*算法……每个点有一个估价函数=g[x]+h[x] 其中g[x]是从源点出发已经走了的长度 h[x]是从这个点到汇点的最短路
首先先在反图上跑一遍SPFA求出每个点的h[x],然后将源点的g[x]+h[x]加入堆 每次取出堆顶时将堆顶的g[x]向所连接的边扩展 第k次取出汇点即是答案
其中有一个剪枝就是当第k+1次取出某个点时不继续拓展 防止MLE 但是这里k未知 我们可以对k进行估价处理 初始k=floor(E/最短路长度) 然后每次取出汇点时更新k k=cnt[n]+floor(E/当前路径长度)
比较丧病的是这题卡priority_queue……这东西的内存是手写堆的二倍 由于卡内存 所以会挂 可以手写堆 我写了可并堆+垃圾回收……
#include
#include
#include
#include
#include
#define M 5050
using namespace std;
struct abcd{
int pos;
double g,h;
bool operator < (const abcd &x) const
{
return g + h < x.g + x.h ;
}
};
struct Heap{
abcd num;
Heap *ls,*rs;
void* operator new (size_t size,int pos,double g,double h);
void operator delete (void* p);
}*root,*mempool,*C;
struct edge{
int to,next;
double f;
}table[400400];
int head[M],tot=1;
bool flag;
queue bin;
int n,m,k,ans,cnt[M];
double e,f[M];
void* Heap :: operator new (size_t size,int pos,double g,double h)
{
if( !bin.empty() )
{
Heap *re=(Heap*)bin.front();
bin.pop();
re->num.pos=pos;
re->num.g=g;
re->num.h=h;
re->ls=re->rs=0x0;
return re;
}
if(C==mempool)
{
C=new Heap[1<<15];
mempool=C+(1<<15);
}
C->num.pos=pos;
C->num.g=g;
C->num.h=h;
C->ls=C->rs=0x0;
return C++;
}
void Heap :: operator delete (void *p)
{
bin.push(p);
}
Heap* Merge(Heap *x,Heap *y)
{
if(!x) return y;
if(!y) return x;
if( y->num < x->num )
swap(x,y);
if(flag^=1)
x->ls=Merge(x->ls,y);
else
x->rs=Merge(x->rs,y);
return x;
}
inline void Insert(int pos,double g,double h)
{
root=Merge(root,new (pos,g,h) Heap);
}
inline void Pop()
{
delete root;
root=Merge(root->ls,root->rs);
}
void Add(int x,int y,double z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
void SPFA()
{
static int q[1<<16];
static unsigned short r,h;
static bool v[M];
int i;
memset(f,0x42,sizeof f);
f[n]=0;q[++r]=n;
while(r!=h)
{
int x=q[++h];v[x]=0;
for(i=head[x];i;i=table[i].next)
if( i&1 && f[table[i].to]>f[x]+table[i].f )
{
f[table[i].to]=f[x]+table[i].f;
if(!v[table[i].to])
v[table[i].to]=1,q[++r]=table[i].to;
}
}
}
void A_Star()
{
int i;
k=static_cast(e/f[1])+1;
Insert(1,0,f[1]);
while(root)
{
abcd x=root->num;Pop();
if( ++cnt[x.pos]>k )
continue;
if(x.pos==n)
{
if(e-x.g<0) return ;
e-=x.g;++ans;
k=cnt[n]+static_cast(e/x.g)+1;
}
for(i=head[x.pos];i;i=table[i].next)
if(~i&1)
Insert(table[i].to,x.g+table[i].f,f[table[i].to]);
}
}
int main()
{
int i,x,y;
double z;
cin>>n>>m>>e;
for(i=1;i<=m;i++)
{
scanf("%d%d%lf",&x,&y,&z);
Add(x,y,z);
Add(y,x,z);
}
SPFA();
A_Star();
cout<