1. 程式人生 > >bzoj1073[SCOI2007]kshort

bzoj1073[SCOI2007]kshort

space bsp img content 例子 long center truct 正整數

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 }

bzoj1073[SCOI2007]kshort