标签:
思路:考试的时候直接想出来了,又有点担心复杂度,不过还是打了,居然是直接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 }
标签:
原文地址:http://www.cnblogs.com/qzqzgfy/p/5633101.html