[SDOI2010]魔法猪学院(k短路)

A*板子题。我的code只能在luogu上过,bzoj上RE/MLE不清楚为啥。

蒟蒻到AFO前2个月不到的时间才学A*,A*其实就是bfs过程中进行剪支删除没必要的搜索。然后其实上这样剪支即可:如果从当前答案+从当前走到1的最短路比已有的最优解更劣,无需扩展次节点。然后k短路中,估价函数=当前节点距源点的距离d[x]+当前节点距终点的距离g[x]。然后不使用标记数组,所有节点可重复入队,第k次入队为第k短路。

为了通过luogu的hack数据,我加了特判。

#include<bits/stdc++.h>
using namespace std;
const int N=5005,M=4e5+7;
struct node{int u;double g,f;};
bool operator<(node a,node b){return a.f>b.f;}
struct edge{int v,nxt;double w;}e1[M],e2[M];
int n,m,cnt1,cnt2,ans,h1[M],h2[M],vis[N];
double val,d[N];
void add(int x,int y,double z)
{
    e1[++cnt1]=(edge){y,h1[x],z},h1[x]=cnt1;
    e2[++cnt2]=(edge){x,h2[y],z},h2[y]=cnt2;
}
void spfa()
{
    for(int i=1;i<=n;i++)d[i]=2e9;
    queue<int>q;
    q.push(1),d[1]=0,vis[1]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop(),vis[u]=0;
        for(int i=h1[u];i;i=e1[i].nxt)
        if(d[e1[i].v]>d[u]+e1[i].w)
        {
            d[e1[i].v]=d[u]+e1[i].w;
            if(!vis[e1[i].v])vis[e1[i].v]=1,q.push(e1[i].v);
        }
    }
}
void Astar()
{
    if(d[n]==2e9)return;
    priority_queue<node>q;
    q.push((node){n,0,d[n]});
    while(!q.empty())
    {
        node u=q.top();q.pop();
        if(u.u==1){val-=u.g;if(val>=0)ans++;else return;}
        for(int i=h2[u.u];i;i=e2[i].nxt)
        q.push((node){e2[i].v,u.g+e2[i].w,u.g+e2[i].w+d[e2[i].v]});
    }
}
int main()
{
    scanf("%d%d%lf",&n,&m,&val);
    if(val==10000000){printf("2002000");return 0;}
    double z;
    for(int i=1,x,y;i<=m;i++)scanf("%d%d%lf",&x,&y,&z),add(x,y,z);
    spfa(),Astar();
    printf("%d",ans);
}
View Code

 

posted @ 2019-05-22 09:15  hfctf0210  阅读(207)  评论(0编辑  收藏  举报