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 }

时间: 2024-12-20 01:20:22

SGU 145的相关文章

SGU 145.Strange People

时间:0.25s空间:4m 题意: 其实就是求无环第K短路. 输入: 给出n,m,k,分别代表,n个点,m条边,第k长路. 接下来m行,三个整数x,y,z,分别代表x,y之间有条费用为x的双向路.保证没有重边. 输出: 第一行两个数a,b,第k小费用a,和经过的点的个数b. 接下来b个数,代表第k短的路径. Sample Input 5 10 3 1 2 6 1 3 13 1 4 18 1 5 35 2 3 14 2 4 34 2 5 17 3 4 22 3 5 15 4 5 34 1 5 Sa

SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流

The Glorious Karlutka River =) Time Limit:500MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 438 Appoint description: Description A group of Mtourists are walking along the Karlutka river. They want to cross

sgu Kalevich Strikes Back

这道题就是求一个大矩形被n个矩形划分成n+1个部分的面积,这些矩形之间不会相交,可能包含.. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #define maxn 120100 6 using namespace std; 7 8 long long s[maxn]; 9 vector<int>g[maxn]; 10 i

sgu 463 - Walking around Berhattan

K - Walking around Berhattan Time Limit:250MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 463 Description As you probably know, Berhattan is a district of Berland's largest city and it consists of equal squar

Cacti Error:&#39;145“解决

早上正常查看监控之一,cacti不出图了.昨天断电了一次.排查: 1.检查服务正常 2.检查服务的连接,正常 3.查看日志,报错145. 日志报错如下: AM - CMDPHP: Poller[0] ERROR: SQL Assoc Failed!, Error:'145', SQL:"select  poller_output.output,  poller_output.time,  poller_output.local_data_id,  poller_item.rrd_path,  p

【SGU 390】Tickets (数位DP)

Tickets Description Conductor is quite a boring profession, as all you have to do is just to sell tickets to the passengers. So no wonder that once upon a time in a faraway galaxy one conductor decided to diversify this occupation. Now this conductor

ACM: SGU 101 Domino- 欧拉回路-并查集

sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Description Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The bl

SGU 116 Index of super-prime 数论+完全背包+输出方案

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=116 题意好晦涩 给你一个不超过一万的数 问它最少可以用多少个“超级素数”来表示 使“超级素数”之和等于它 如果无法这样表示 输出0 否则 按非降序形式输出方案 数论部分就模板的问题 没什么说的 完全背包方面也很常规 说说[输出方案] 背包九讲的伪码给的是二维dp[]的方法 实际上稍加改动就可以用在一维数组上 用一个rec[]记录dp[]的当前状态是从哪个状态转移而来(即上一个状态) 通过

SGU 乱搞日志

SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注意自环,连通 1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #i