bzoj1073[SCOI2007]kshort
1073: [SCOI2007]kshort
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 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
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
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.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。