XJOI网上同步训练DAY6 T1

 

思路:考试的时候直接想出来了,又有点担心复杂度,不过还是打了,居然是直接A掉,开心啊。

我们发现,Ai<=7,这一定是很重要的条件,我们考虑状态压缩,去枚举路径中出现了哪些数字,然后我们把原来n个点拆成 我们枚举数字的最小公倍数 个,因为如果一个数模某个数等于0,那么模它的因数也一定是0,因此我们的思路就是拆点最短路。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<iostream>
 6 const int p[25]={1,2,3,4,5,6,7,10,12,14,15,20,21,28,30,35,42,60,70,84,105,140,210,420};
 7 int tot,go[200005],first[200005],next[200005];
 8 struct edge{
 9     int u,v;
10 }e[50005];
11 int a[200005],n,m,vis[5005][505],dis[5005][505],c[2000005][2];
12 int read(){
13      int t=0,f=1;char ch=getchar();
14      while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
15      while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
16      return t*f;
17 }
18 void insert(int x,int y){
19      tot++;
20      go[tot]=y;
21      next[tot]=first[x];
22      first[x]=tot;
23 }
24 void add(int x,int y){
25      insert(x,y);insert(y,x);
26 }
27 int gcd(int a,int b){
28      if (b==0) return a;
29          else return gcd(b,a%b);
30 }
31 void build(int Mod){
32     for (int i=1;i<=n;i++) first[i]=0;tot=0;
33     for (int i=1;i<=m;i++){
34         if (Mod%a[e[i].u]!=0) continue;
35         if (Mod%a[e[i].v]!=0) continue;
36         add(e[i].u,e[i].v);
37     }
38 }
39 int spfa(int Mod){
40      build(Mod);
41      for (int i=1;i<=n;i++)
42       for (int j=0;j<Mod;j++)
43        dis[i][j]=0x3f3f3f3f,vis[i][j]=0;
44      int h=1,t=1;c[h][0]=1;c[h][1]=a[1]%Mod;
45      vis[1][0]=1;dis[1][a[1]%Mod]=a[1]; 
46      while (h<=t){
47             int nowx=c[h][0],nowy=c[h++][1];
48             for (int i=first[nowx];i;i=next[i]){
49                 int pur1=go[i],pur2=((nowy*10%Mod)+a[pur1])%Mod;
50                 if (dis[pur1][pur2]>dis[nowx][nowy]+a[pur1]){
51                     dis[pur1][pur2]=dis[nowx][nowy]+a[pur1];
52                     if (vis[pur1][pur2]) continue;
53                     vis[pur1][pur2]=1;
54                     t++;
55                     c[t][0]=pur1;c[t][1]=pur2;
56                 }
57             }
58             vis[nowx][nowy]=0;
59      }
60     return dis[n][0];
61 }
62 void solve(){
63      int ans=0x3f3f3f3f;
64      int sb=a[1]*a[n]/gcd(a[1],a[n]);
65      for (int i=0;i<24;i++)
66       if (p[i]%sb==0){
67         ans=std::min(ans,spfa(p[i]));
68       }
69      if (ans==0x3f3f3f3f) ans=-1;
70      printf("%d\n",ans);
71 }
72 int main(){
73      int T=read();
74      while (T--){
75         n=read();m=read();
76         for (int i=1;i<=n;i++) first[i]=0;tot=0;
77         for (int i=1;i<=n;i++) a[i]=read();
78         for (int i=1;i<=m;i++){
79              e[i].u=read();e[i].v=read();
80         }
81         solve();
82      }
83 }

 

posted @ 2016-07-01 14:55  GFY  阅读(177)  评论(0编辑  收藏  举报