hdu3247Resource Archiver(ac自动机+spfa)

链接

这题没想到怎么做,问了下p队长,大悟。。

先求出任意两串的在trie树上的最短距离,期间是不能走到不合法的地方,我是用spfa求得,在更新和加入节点时判断一下是不是合法位置。

求出最短距离之后,找出一条从0出发遍历所有串的最短距离,可以dp出,dp[i][j]表示当前状态以节点j串结尾的最短距离。

枚举一下最后结尾的为哪一个串时距离最短。

  1 #include <iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<stdlib.h>

  6 #include<vector>

  7 #include<cmath>

  8 #include<queue>

  9 #include<set>

 10 using namespace std;

 11 #define N 60010

 12 #define M 10010

 13 #define LL long long

 14 #define INF 0xfffffff

 15 const double eps = 1e-8;

 16 const double pi = acos(-1.0);

 17 const double inf = ~0u>>2;

 18 const int child_num = 2;

 19 int w[15][15];

 20 bool vis[N];

 21 int dis[N];

 22 class AC

 23 {

 24     private:

 25     int ch[N][child_num];

 26     int fail[N];

 27     int Q[N];

 28     int val[N],vv[N];

 29     int id[127];

 30     int sz ;

 31     int po[12];

 32     int dp[2110][12];

 33     public:

 34     void init()

 35     {

 36         fail[0] = 0;

 37         id['1'] = 1;

 38         id['0'] = 0;

 39     }

 40     void reset()

 41     {

 42         memset(ch[0],0,sizeof(ch[0]));

 43         memset(val,0,sizeof(val));

 44         memset(vv,0,sizeof(vv));

 45         sz=1;

 46     }

 47     void insert(char *a ,int key)

 48     {

 49         int p =0 ;

 50         for( ; *a ; a++)

 51         {

 52             int d = id[*a];

 53             if(ch[p][d]==0)

 54             {

 55                 memset(ch[sz],0,sizeof(ch[sz]));

 56                 ch[p][d] = sz++;

 57             }

 58             p = ch[p][d];

 59         }

 60         if(key!=-1)

 61         {

 62             val[p] = 1<<(key-1);

 63             po[key] = p;

 64         }

 65         else

 66         {

 67             vv[p] = 1;

 68         }

 69     }

 70     void construct()

 71     {

 72         int i,head=0,tail = 0;

 73         for(i = 0; i < child_num ; i++)

 74         if(ch[0][i])

 75         {

 76             fail[ch[0][i]] = 0;

 77             Q[tail++] = ch[0][i];

 78         }

 79         while(head!=tail)

 80         {

 81             int u = Q[head++];

 82             vv[u]|=vv[fail[u]];

 83             val[u]|=val[fail[u]];

 84             for(i = 0 ;i < child_num ; i++)

 85             {

 86                 if(ch[u][i])

 87                 {

 88                     fail[ch[u][i]] = ch[fail[u]][i];

 89                     Q[tail++] = ch[u][i];

 90                 }

 91                 else ch[u][i] = ch[fail[u]][i];

 92             }

 93         }

 94     }

 95     int spfa(int st,int ed)

 96     {

 97         int i;

 98         memset(vis,0,sizeof(vis));

 99         for(i = 0; i <= sz ;i++)

100         dis[i] = INF;

101         dis[st] = 0;

102         vis[st] = 1;

103         queue<int>q;

104         q.push(st);

105         while(!q.empty())

106         {

107             int u = q.front();

108             q.pop();

109             for(i = 0 ; i < child_num; i++)

110             {

111                 int v = ch[u][i];

112                 if(vv[v]) continue;

113                 dis[v] = min(dis[v],dis[u]+1);

114                 //if(st == 4&&ed==8)

115                 //cout<<v<<" "<<dis[v]<<" "<<u<<endl;

116                 if(!vis[v])

117                 {

118                     vis[v] = 1;

119                     q.push(v);

120                 }

121             }

122         }

123         return dis[ed];

124     }

125     void find_dis(int n)

126     {

127         int i,j;

128         po[0] = 0;

129         for(i = 1; i <= n ;i++)

130         {

131             w[0][i] = w[i][0] = spfa(0,po[i]);

132             //cout<<w[0][i]<<endl;

133         }

134         for(i = 1; i <= n; i++)

135             for(j = 1 ; j <= n ;j++)

136             {

137                 w[i][j] = spfa(po[i],po[j]);

138                // cout<<w[i][j]<<" "<<i<<" "<<j<<endl;

139             }

140     }

141     void work(int n)

142     {

143         int i,j,g;

144         for(i = 0 ; i < (1<<n) ; i++)

145             for(j = 0;j <= n; j++)

146             dp[i][j] = INF;

147         dp[0][0] = 0;

148         for(i = 0 ;i < (1<<n) ; i++)

149         {

150             for(j = 0 ;j <= n ;j++)

151             {

152                 for(g = 0 ; g <= n ;g++)

153                 {

154                     if((1<<(g-1))&i) continue;

155                     dp[i+(1<<(g-1))][g] = min(dp[i+(1<<(g-1))][g],dp[i][j]+w[j][g]);

156                 }

157             }

158         }

159         int ans = INF;

160         for(i = 1 ; i <= n ; i++)

161         ans = min(ans,dp[(1<<n)-1][i]);

162         cout<<ans<<endl;

163     }

164 }ac;

165 char vir[50010],re[1010];

166 int main()

167 {

168     int n,m,i;

169     ac.init();

170     while(scanf("%d%d",&n,&m)&&n&&m)

171     {

172         ac.reset();

173         for(i = 1; i <= n ;i++)

174         {

175             scanf("%s",re);

176             ac.insert(re,i);

177         }

178         while(m--)

179         {

180             scanf("%s",vir);

181             ac.insert(vir,-1);

182         }

183         ac.construct();

184         ac.find_dis(n);

185         ac.work(n);

186     }

187     return 0;

188 }
View Code

 

你可能感兴趣的:(resource)