SGU 145
节点不可重复经过的K短路问题。
思路:二分路径长度,深搜小于等于路径长度的路径数。可以利用可重复点K短路问题中的A*函数进行剪枝。
尝试另一种解法:把可重复点K短路A*直接搬过来,堆中的每个元素额外记录之前走过的所有点。这样就可以据此防止走重复的点。最大100个点,可用两个长整形状态压缩。
一直PE,无法验证效率。
1 #include <map> 2 #include <set> 3 #include <list> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <vector> 8 #include <cstdio> 9 #include <string> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef long long ll; 16 17 #define eps 1e-8 18 #define inf 0x7f3f3f3f 19 #define debug puts("BUG") 20 #define read freopen("in.txt","r",stdin) 21 22 #define N 111 23 #define M 11111 24 struct node 25 { 26 int v,w,n; 27 }ed[M],ed2[M]; 28 int head[N],head2[N],cnt,cnt2; 29 struct str 30 { 31 int v,p; 32 }st[M*10]; 33 struct node2 34 { 35 int v,g,f,dx; 36 ll m1,m2; 37 void set(int _v,int _g,int _f,int dx,ll m1,ll m2) 38 { 39 this->v = _v; 40 this->g = _g; 41 this->f = _f; 42 this->dx = dx; 43 this->m1 = m1; 44 this->m2 = m2; 45 } 46 bool operator < (const node2 &n) const 47 { 48 if (n.f == f) return n.g < g; 49 return n.f < f; 50 } 51 }; 52 void sc(int s,ll &m1,ll &m2) 53 { 54 if (s>50) m2 |= ((s-51)<<1); 55 else m1 |= ((s-1)<<1); 56 } 57 bool ck(int s,ll m1,ll m2) 58 { 59 if (s>50) return (m2&((s-51)<<1)) != 0; 60 else return (m1&((s-1)<<1)) != 0; 61 } 62 void init() 63 { 64 memset(head,-1,sizeof(head)); 65 memset(head2,-1,sizeof(head2)); 66 cnt = cnt2 = 0; 67 } 68 void add(int u,int v,int w) 69 { 70 ed[cnt].v = v; 71 ed[cnt].w = w; 72 ed[cnt].n = head[u]; 73 head[u] = cnt++; 74 ed2[cnt2].v = u; 75 ed2[cnt2].w = w; 76 ed2[cnt2].n = head2[v]; 77 head2[v] = cnt2++; 78 } 79 int h[N]; 80 bool vis[N]; 81 void spfa(int s,int n) 82 { 83 queue<int>q; 84 memset(vis,0,sizeof(vis)); 85 for (int i = 1; i <= n; ++i) 86 h[i] = inf; 87 q.push(s); 88 h[s] = 0; 89 vis[s] = true; 90 while (!q.empty()) 91 { 92 int u = q.front(); 93 q.pop(); 94 vis[u] = false; 95 for (int i=head2[u];~i;i=ed2[i].n) 96 { 97 int v = ed2[i].v,w = ed2[i].w; 98 if (h[v]>h[u]+w) 99 { 100 h[v] = h[u] + w; 101 if (!vis[v]) 102 { 103 vis[v] = true; 104 q.push(v); 105 } 106 } 107 } 108 } 109 } 110 int ans[N]; 111 void astar(int s,int t,int k) 112 { 113 priority_queue<node2> q; 114 int cnt = 0, dx = 0; 115 node2 n,n2; 116 ll m1=0,m2=0; 117 sc(s,m1,m2); 118 st[dx].p = -1,st[dx].v = s; 119 n.set(s,0,h[s],dx++,m1,m2); 120 q.push(n); 121 while (!q.empty()) 122 { 123 n = q.top(); 124 q.pop(); 125 if (n.v == t) cnt++; 126 if (cnt == k) 127 { 128 int a = n.dx, b = 0; 129 while (~a) 130 { 131 ans[b++] = st[a].v; 132 a = st[a].p; 133 } 134 printf("%d %d\n",n.g,b); 135 bool ff = false; 136 for (int i = b-1; i >= 0; --i) 137 { 138 if (ff) printf(" "); 139 else ff = true; 140 printf("%d",ans[i]); 141 }puts(""); 142 return ; 143 } 144 for (int i=head[n.v];~i;i=ed[i].n) 145 { 146 int v = ed[i].v, w = ed[i].w; 147 m1 = n.m1, m2 = n.m2; 148 if (ck(v,m1,m2)) continue; 149 sc(v,m1,m2); 150 st[dx].p = n.dx, st[dx].v = v; 151 n2.set(v,n.g+w,n.g+w+h[v],dx++,m1,m2); 152 q.push(n2); 153 } 154 } 155 return ; 156 } 157 int main() 158 { 159 //read; 160 int n,m,k; 161 while (~scanf("%d%d%d",&n,&m,&k)) 162 { 163 init(); 164 int u,v,w,s,t; 165 for (int i = 0; i < m; ++i) 166 { 167 scanf("%d%d%d",&u,&v,&w); 168 add(u,v,w); 169 } 170 scanf("%d%d",&s,&t); 171 spfa(t,n); 172 astar(s,t,k); 173 } 174 return 0; 175 }