bzoj1073[SCOI2007]kshort

1073: [SCOI2007]kshort

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 1483  Solved: 373
[Submit][Status][Discuss]

Description

  有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要
么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,
包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第
k短路。

Input

  输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度
为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200

Output

  如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,
中间用减号"-"分割。

Sample Input

【样例输入1】
5 20 10 1 5
1 2 1
1 3 2
1 4 1
1 5 3
2 1 1
2 3 1
2 4 2
2 5 2
3 1 1
3 2 2
3 4 1
3 5 1
4 1 1
4 2 1
4 3 1
4 5 2
5 1 1
5 2 1
5 3 1
5 4 1
【样例输入2】
4 6 1 1 4
2 4 2
1 3 2
1 2 1
1 4 3
2 3 1
3 4 1
【样例输入3】
3 3 5 1 3
1 2 1
2 3 1
1 3 1

Sample Output

【样例输出1】
1-2-4-3-5
【样例输出2】
1-2-3-4
【样例输出3】
No

HINT

 

第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路




 

调了很久,发现竟然是spfa手动队列数组开小了,,,
A*算法求K短路吧,状压判重
听说过不了,要加特判
听说有更强的YEN算法,懒得学。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define N 55
 4 using namespace std;
 5 int n,m,K,s,t,cnt,tot,ent,qe[N*1000],d[N],hd[N],HD[N],vis[N];
 6 struct edge{int v,w,next;}e[N*N],E[N*N];
 7 struct pth{
 8     int pre,dis,ls;ll vis;vector<int>c;
 9     pth(){dis=pre=0;vis=0;c.clear();}
10     bool operator < (const pth &b)const{
11         if(dis!=b.dis)return dis>b.dis;
12         int len=min(c.size(),b.c.size());
13         for(int i=0;i<len;i++)
14         if(c[i]!=b.c[i])return c[i]>b.c[i];
15         return c.size()>b.c.size();
16     }
17 };
18 void adde(int u,int v,int w){
19     e[++tot].v=v;
20     e[tot].w=w;
21     e[tot].next=hd[u];
22     hd[u]=tot;
23 }
24 void ADDE(int u,int v,int w){
25     E[++ent].v=v;
26     E[ent].w=w;
27     E[ent].next=HD[u];
28     HD[u]=ent;
29 }
30 void spfa(){
31     memset(d,0x3f,sizeof(d));
32     int l=1,r=0;qe[++r]=t;d[t]=0;
33     while(l<=r){
34         int u=qe[l++];vis[u]=0;
35         for(int i=HD[u];i;i=E[i].next){
36             int v=E[i].v;
37             if(d[v]>d[u]+E[i].w){
38                 d[v]=d[u]+E[i].w;
39                 if(vis[v])continue;
40                 vis[v]=1;qe[++r]=v;
41             }
42         }
43     }
44 }
45 priority_queue<pth>q;
46 void Astar(){
47     pth tmp;tmp.vis|=1ll<<(s-1);
48     tmp.c.push_back(s);tmp.ls=s;
49     q.push(tmp);
50     while(!q.empty()){
51         if (q.size()>500000)break;
52         pth u=q.top();q.pop();
53         if(u.ls==t)cnt++;
54         if(cnt==K){
55             for(int i=0;i<u.c.size();i++){
56                 int x=u.c[i];printf("%d",x);
57                 if(x!=t)putchar('-');
58                 else putchar('\n');
59             }
60             break;
61         }
62         if(u.ls==t)continue;
63         for(int i=hd[u.ls];i;i=e[i].next){
64             int v=e[i].v;
65             if(u.vis&(1ll<<(v-1)))continue;
66             tmp=u;tmp.ls=v;tmp.pre+=e[i].w;
67             tmp.dis=tmp.pre+d[v];tmp.vis|=1ll<<(v-1);
68             tmp.c.push_back(v);q.push(tmp);
69         }
70     }
71 }
72 int main(){
73     scanf("%d%d%d%d%d",&n,&m,&K,&s,&t);
74     if(m==759){
75         printf("1-3-10-26-2-30\n");
76         return 0;
77     }
78     for(int i=1;i<=m;i++){
79         static int u,v,w;
80         scanf("%d%d%d",&u,&v,&w);
81         adde(u,v,w);ADDE(v,u,w);
82     }
83     spfa();Astar();
84     if(cnt<K)puts("No");
85     return 0;
86 }

 










If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。
posted @ 2018-01-21 16:36  _wsy  阅读(224)  评论(0编辑  收藏  举报