BZOJ1598: [Usaco2008 Mar]牛跑步

n<=1000而m<=10000的DAG中求从n到1的前K<=100短路,不存在输出-1。

方法一:之前写过“第二短路”,比较2次;如果是要“前K短路”的话,dis需要是一个支持查找、插入(找到一个新的第u大,u<=K,需要插入u)、删除(插入后把最后一个删除)的东西,那就Treap或者Splay乱写一通啦。代码如下:

如下个头。编程复杂度不说,一定要用SPFA实现,正确性不明,时间复杂度也难说。

方法二:查了题解。根据数据规模和图的特点选择A*:数据n和K都较小,可以感觉,从起点n到其它点的路程中,第v,v>=K+1短路是没有意义的;图没有环。

所以A*中,估价函数h=当前状态的运动路程+从这个点到终点的最短路。为了得到后者,需把所有的边反过来找1到每个点的最短路。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<queue>
  6 //#include<iostream>
  7 using namespace std;
  8 
  9 int n,m,K;
 10 #define maxn 1011
 11 #define maxm 10011
 12 struct Edge{int to,v,next;};
 13 const int inf=0x7fffffff;
 14 struct Graph
 15 {
 16     Edge edge[maxm*2];int le;
 17     int first[maxn],dis[maxn],vis[maxn];
 18     struct Node
 19     {
 20         int x,v;
 21         bool operator < (const Node &b) const {return v<b.v;}
 22         bool operator > (const Node &b) const {return v>b.v;}
 23     };
 24     priority_queue<Node,vector<Node>,greater<Node> > q;
 25     Graph()
 26     {
 27         memset(first,0,sizeof(first));
 28         le=2;
 29     }
 30     void insert(int x,int y,int v)
 31     {
 32         Edge &e=edge[le];
 33         e.to=y;e.v=v;
 34         e.next=first[x];
 35         first[x]=le++;
 36     }
 37     void Dijkstra()
 38     {
 39         for (int i=1;i<=n;i++) dis[i]=inf;
 40         memset(vis,0,sizeof(vis));
 41         dis[1]=0;
 42         q.push((Node){1,0});
 43         while (!q.empty())
 44         {
 45             const int now=q.top().x,d=q.top().v;
 46             q.pop();
 47             if (vis[now]) continue;
 48             vis[now]=1;
 49             for (int i=first[now];i;i=edge[i].next)
 50                 if (dis[edge[i].to]>d+edge[i].v)
 51                 {
 52                     dis[edge[i].to]=d+edge[i].v;
 53                     q.push((Node){edge[i].to,dis[edge[i].to]});
 54                 }
 55         }
 56     }
 57 }reG,G;
 58 struct heapnode
 59 {
 60     int x,f,g;
 61     bool operator < (const heapnode &b) const
 62     {return f+g<b.f+b.g;}
 63     bool operator > (const heapnode &b) const
 64     {return f+g>b.f+b.g;}
 65 };
 66 priority_queue<heapnode,vector<heapnode>,greater<heapnode> > que;
 67 int ans[maxn],cnt[maxn];
 68 void Astar()
 69 {
 70     que.push((heapnode){n,0,reG.dis[n]});
 71     cnt[n]=1;
 72     while (!que.empty())
 73     {
 74         const int x=que.top().x,d=que.top().f;
 75         que.pop();
 76         if (cnt[x]==K) continue;
 77         cnt[x]++;
 78         if (x==1)
 79         {
 80             ans[cnt[x]]=d;
 81             if (cnt[x]==K) break;
 82         }
 83         for (int i=G.first[x];i;i=G.edge[i].next)
 84             que.push((heapnode){G.edge[i].to,G.edge[i].v+d,reG.dis[G.edge[i].to]});
 85     }
 86 }
 87 int x,y,v;
 88 int main()
 89 {
 90     scanf("%d%d%d",&n,&m,&K);
 91     for (int i=1;i<=m;i++)
 92     {
 93         scanf("%d%d%d",&x,&y,&v);
 94         G.insert(x,y,v);
 95         reG.insert(y,x,v);
 96     }
 97     reG.Dijkstra();
 98     memset(ans,-1,sizeof(ans));
 99     Astar();
100     for (int i=1;i<=K;i++) printf("%d\n",ans[i]);
101     return 0;
102 }
View Code

 

posted @ 2017-07-26 17:15  Blue233333  阅读(275)  评论(0编辑  收藏  举报