[SCOI2007]kshort--k短路
[SCOI2007]kshort
【题目描述】
有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。
【输入格式】
输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度
为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200
【输出格式】
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
【样例输入】
【样例输入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
【样例输出】
【样例输出1】 1-2-4-3-5 【样例输出2】 1-2-3-4 【样例输出3】 No
【提示】
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路
序号 | 长度 | 路径 |
1 | 3 | 1-2-3-5 |
2 | 3 | 1—2—5 |
3 | 3 | 1—3—5 |
4 | 3 | 1—4—3—5 |
5 | 3 | 1—4—5 |
6 | 3 | 1—5 |
7 | 4 | 1—4—2—3—5 |
8 | 4 | 1—4—2—5 |
9 | 5 | 1—2—3—4—5 |
10 | 5 | 1—2—4—3—5 |
11 | 5 | 1—2—4—5 |
12 | 5 | 1—3—4—5 |
13 | 6 | 1—3—2—5 |
14 | 6 | 1—3—4—2—5 |
15 | 6 | 1—4—3—2—5 |
16 | 8 | 1—3—2—4—5 |
【来源】
这道题只是由于做题人被坑了好长时间才弄上来的,数据来自Tyvj极其丧心病狂因此把内存开到 1G ,希望大家嚎嚎享受。
然而事实证明即使内存开到1G也还是过不了第⑥个点,希望能看到不打表的 袋马 。_(:з」∠)_
k短路
然而他卡A*
只好打表喽(/理直气壮)。。
1 #include <algorithm> 2 #include <ctype.h> 3 #include <vector> 4 #include <cstdio> 5 #include <queue> 6 7 using namespace std; 8 9 const int MAXM=10010; 10 const int MAXN=55; 11 const int INF=0x7fffffff; 12 13 int n,m,k,S,T,sum; 14 15 int dist[MAXN]; 16 17 struct node { 18 int to; 19 int next; 20 int val; 21 node() {} 22 node (int to,int val,int next):to(to),val(val),next(next) {} 23 }; 24 node e[MAXM<<1],r[MAXM<<1]; 25 26 int head[MAXN],tot,head1[MAXN]; 27 28 bool visit[MAXN]; 29 30 inline void read(int&x) { 31 int f=1;register char c=getchar(); 32 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 33 for(;isdigit(c);x=x*10+c-48,c=getchar()); 34 x=x*f; 35 } 36 37 struct data { 38 int u,dis; 39 vector<int> path; 40 bool vis[MAXN]; 41 friend bool operator < (data k,data p) { 42 return k.dis+dist[k.u]>p.dis+dist[p.u]; 43 } 44 }; 45 data s; 46 47 inline bool cmp(data f,data l) { 48 if(f.dis!=l.dis) return f.dis<l.dis; 49 int Len=min(f.path.size(),l.path.size()); 50 for(int i=0;i<Len;++i) { 51 if(f.path[i]<l.path[i]) return true; 52 else if(f.path[i]>l.path[i]) return false; 53 } 54 return f.path.size()<l.path.size(); 55 } 56 57 inline void add(int x,int y,int z) { 58 e[++tot]=node(y,z,head[x]); 59 r[tot]=node(x,z,head1[y]); 60 head[x]=head1[y]=tot; 61 } 62 63 void spfa() { 64 queue<int> Q; 65 for(int i=1;i<=n;++i) dist[i]=INF,visit[i]=false; 66 dist[T]=0; 67 visit[T]=true; 68 Q.push(T); 69 while(!Q.empty()) { 70 int u=Q.front(); 71 Q.pop(); 72 visit[u]=false; 73 for(int i=head1[u];i;i=r[i].next) { 74 int to=r[i].to; 75 if(dist[to]>dist[u]+r[i].val) { 76 dist[to]=dist[u]+r[i].val; 77 if(!visit[to]) 78 Q.push(to),visit[to]=true; 79 } 80 } 81 } 82 } 83 84 void Astar() { 85 priority_queue<data> Q; 86 vector<data> ans; 87 s.u=S;s.dis=0;s.vis[S]=1; 88 s.path.push_back(S); 89 Q.push(s); 90 while(!Q.empty()) { 91 data u=Q.top(); 92 Q.pop(); 93 if(u.u==T) { 94 ++sum; 95 if(sum>k&&u.dis>ans[k-1].dis) break; 96 ans.push_back(u); 97 } 98 for(int i=head[u.u];i;i=e[i].next) { 99 int to=e[i].to; 100 if(u.vis[to]) continue; 101 data t=u; 102 t.u=to; 103 t.dis=u.dis+e[i].val; 104 t.path.push_back(t.u); 105 t.vis[t.u]=true; 106 Q.push(t); 107 } 108 } 109 if(ans.size()<k) { 110 printf("No\n"); 111 return; 112 } 113 sort(ans.begin(),ans.end(),cmp); 114 for(int i=0;i<ans[k-1].path.size();++i) 115 printf("%d%c",ans[k-1].path[i],i==ans[k-1].path.size()-1?'\n':'-'); 116 return; 117 } 118 119 int hh() { 120 freopen("bzoj_1073.in","r",stdin); 121 freopen("bzoj_1073.out","w",stdout); 122 int x,y,z; 123 read(n);read(m);read(k);read(S);read(T); 124 if(m==759){ 125 printf("1-3-10-26-2-30\n"); 126 return 0; 127 } 128 for(int i=1;i<=m;++i) { 129 read(x);read(y);read(z); 130 add(x,y,z); 131 } 132 spfa(); 133 Astar(); 134 return 0; 135 } 136 137 int sb=hh(); 138 int main() {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现