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 }
View Code

 

转载于:https://www.cnblogs.com/mcflurry/p/5069083.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值