码迷,mamicode.com
首页 > 其他好文 > 详细

HDU4511 AC自动机+dijkstra

时间:2016-10-30 07:10:28      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:push   min   blog   朋友   规则   小明   insert   priority   clear   

题意:

Description

  终于放寒假了,小明要和女朋友一起去看电影。这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: 
  1、假设小明在的位置是1号点,女朋友在的位置是n号点,则他们之间有n-2个点可以走,小明每次走的时候只能走到比当前所在点编号大的位置; 
  2、小明来的时候不能按一定的顺序经过某些地方。比如,如果女朋友告诉小明不能经过1 -> 2 -> 3,那么就要求小明来的时候走过的路径不能包含有1 -> 2 -> 3这部分,但是1 -> 3 或者1 -> 2都是可以的,这样的限制路径可能有多条。 
  这让小明非常头痛,现在他把问题交给了你。 
  特别说明,如果1 2 3这三个点共线,但是小明是直接从1到3然后再从3继续,那么此种情况是不认为小明经过了2这个点的。 
  现在,小明即想走最短的路尽快见到女朋友,又不想打破女朋友的规定,你能帮助小明解决这个问题吗?

Input

  输入包含多组样例,每组样例首先包含两个整数n和m,其中n代表有n个点,小明在1号点,女朋友在n号点,m代表小明的女朋友有m个要求; 
  接下来n行每行输入2个整数x 和y(x和y均在int范围),代表这n个点的位置(点的编号从1到n); 
  再接着是m个要求,每个要求2行,首先一行是一个k,表示这个要求和k个点有关,然后是顺序给出的k个点编号,代表小明不能走k1 -> k2 -> k3 ……-> ki这个顺序的路径; 
  n 和 m等于0的时候输入结束。 

   [Technical Specification] 
  2 <= n <= 50 
  1 <= m <= 100 
  2 <= k <= 5 

Output

  对于每个样例,如果存在满足要求的最短路径,请输出这个最短路径,结果保留两位小数;否则,请输出”Can not be reached!” (引号不用输出)。
 
  1 #include <bits/stdc++.h>
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <algorithm>
  5 #define ll long long
  6 #define lson l, m, rt<<1
  7 #define rson m+1, r, rt<<1|1
  8 #define st first
  9 #define nd second
 10 #define mp make_pair
 11 #define pii pair<int, int>
 12 #define pdi pair<double, int>
 13 #define gg puts("gg");
 14 //#define local
 15 //#define out1
 16 using namespace std;
 17 const int N  = 6e4+10;
 18 const int inf = 0x3f3f3f3f;
 19 int id(int c){
 20     return c-1;
 21 }
 22 struct Tire{
 23     int nex[N][50], fail[N],end[N], ch[N];
 24     int root, L, tot;
 25     int newnode(){
 26         memset(nex[L], -1, sizeof(nex[L]));
 27         end[L] = 0;
 28         ch[L] = 0;
 29         return L++;
 30     }
 31     void init(){
 32         L = tot = 0;
 33         root = newnode();
 34     }
 35     void insert(int* s, int len, int tag){
 36         int now = root;
 37         for(int i = 0; i < len; i++){
 38             int p = id(s[i]);
 39             if(nex[now][p] == -1)
 40                 nex[now][p] = newnode();
 41             now = nex[now][p];
 42             ch[now] = p;
 43         }
 44         end[now] = tag;
 45     }
 46     void build(){
 47         queue<int> Q;
 48         fail[root] = root;
 49         for(int i = 0; i < 50; i++){
 50             int& u = nex[root][i];
 51             if(u == -1)
 52                 u = root;
 53             else{
 54                 fail[u] = root;
 55                 Q.push(u);
 56             }
 57         }
 58         while(!Q.empty()){
 59             int now = Q.front();
 60             Q.pop();
 61             for(int i = 0; i < 50; i++){
 62                 int& u = nex[now][i];
 63                 if(u == -1)
 64                     u = nex[ fail[now] ][i];
 65                 else{
 66                     fail[u] = nex[ fail[now] ][i];
 67                     end[u] |= end[ fail[u] ];
 68                     Q.push(u);
 69                 }
 70             }
 71         }
 72     }
 73 };
 74 Tire ac;
 75 ll x[55], y[55];
 76 double w[55][55];
 77 int s[10];
 78 vector< pdi > ve[505];
 79 priority_queue< pdi, vector< pdi >, greater< pdi > >Q;
 80 double d[505];
 81 double dijkstra(int S){
 82     int i, x;
 83     for(i = 0; i < 505; i++) d[i] = 1e30;
 84     Q.push(mp(d[S]=0,S));
 85     while(!Q.empty()){
 86         pdi t = Q.top(); Q.pop();
 87         if(d[x = t.nd] < t.st) continue;
 88         for(i = 0; i < ve[x].size(); i++)
 89             if(d[x]+ve[x][i].st < d[ve[x][i].nd]){
 90                 d[ve[x][i].nd] = d[x]+ve[x][i].st;
 91                 Q.push( mp(d[ve[x][i].nd], ve[x][i].nd) );
 92             }
 93     }
 94 }
 95 int main(){
 96     int n, m, ca = 1;
 97     while(~scanf("%d%d", &n, &m), n+m){
 98         for(int i = 1; i <= n; i++)
 99             scanf("%lld%lld", x+i, y+i);
100         for(int i = 0; i <= n; i++)
101             for(int j = 0; j <= n; j++) w[i][j] = 1e30;
102         for(int i = 1; i <= n; i++)
103             for(int j = i+1; j <= n; j++)
104                 w[i][j] = sqrt( 1.0*(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]) );
105 
106         ac.init();
107         for(int i = 1; i <= n; i++){
108             s[0] = i;
109             ac.insert(s, 1, 0);
110         }
111 
112         for(int i = 1; i <= m; i++){
113             int k; scanf("%d", &k);
114             for(int j = 0; j < k; j++)
115                 scanf("%d", s+j);
116             ac.insert(s, k, 1);
117         }
118         ac.build();
119         for(int i = 0; i < ac.L; i++) ve[i].clear();
120         for(int i = 1; i < ac.L; i++){
121             int u = ac.ch[i]+1;
122             for(int j = u+1; j <= n; j++) {
123                 int to = ac.nex[i][id(j)];
124                 if(!ac.end[to]) ve[i].push_back( mp(w[u][j], to) );
125             }
126         }
127 
128         dijkstra(ac.nex[0][id(1)]);
129         double ans = 1e30;
130         for(int i = 1; i < ac.L; i++){
131             if(ac.ch[i] == id(n))
132                 ans = min(ans, d[i]);
133         }
134         if(ans < 1e25)
135             printf("%.2f\n", ans);
136         else
137             puts("Can not be reached!");
138     }
139     return 0;
140 }

 

后记:发现debug能力实在太弱了...调半天没看出来哪错了...代码能力不够啊!!!

 

HDU4511 AC自动机+dijkstra

标签:push   min   blog   朋友   规则   小明   insert   priority   clear   

原文地址:http://www.cnblogs.com/dirge/p/6012301.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!