51nod 1693 水群(Dijkstra)
Posted 7391_KID
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1693 水群(Dijkstra)相关的知识,希望对你有一定的参考价值。
分析:一开始想暴力dp,但是有环,不好处理。。考虑建一个图,从k向k-1连一条边权为1,向i*k连一条边权i*k的边,然后Dijkstra,复杂度为O(nlogn(loglog(n)),然而这数据范围。。这时间限制。。
可以简化,只连k乘一个质数p的边,并且p<=13,虽然并不会证明。。可以用未优化过的打个表,发现答案不超过43,因此至少在这个范围内是可行的。。
Dijkstra一开始常数太大了,因为是把边加进去再做的,可以优化成直接利用点得到边。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 #include<vector> 6 using namespace std; 7 const int maxn=1e6+10; 8 int pri[100],len=0; 9 struct Edge{ 10 int from,to,dist; 11 Edge(int u,int v,int d):from(u),to(v),dist(d){} 12 }; 13 struct Node{ 14 int d,u; 15 Node(int d0,int u0):d(d0),u(u0){} 16 }; 17 bool operator < (Node a,Node b){ 18 return a.d>b.d; 19 } 20 struct Dijkstra{ 21 int n; 22 int d[maxn]; 23 void dijkstra(int s){ 24 priority_queue<Node> q; 25 for(int i=0;i<n;i++)d[i]=1e9; 26 d[s]=0; 27 q.push(Node(0,s)); 28 while(!q.empty()){ 29 Node x=q.top(); 30 q.pop(); 31 int u=x.u; 32 if(d[u]!=x.d)continue; 33 for(int i=0;i<len&&pri[i]*u<=n;i++){ 34 if(d[pri[i]*u]>d[u]+pri[i]){ 35 d[pri[i]*u]=d[u]+pri[i]; 36 q.push(Node(d[pri[i]*u],pri[i]*u)); 37 } 38 } 39 if(u>0&&d[u-1]>d[u]+1){ 40 d[u-1]=d[u]+1; 41 q.push(Node(d[u-1],u-1)); 42 } 43 } 44 } 45 }dij; 46 void CalPri(){ 47 int maxn=14; 48 bool no_Pri[maxn]; 49 memset(no_Pri,0,sizeof(no_Pri)); 50 for(int i=2;i<maxn;i++){ 51 if(!no_Pri[i]){ 52 pri[len++]=i; 53 } 54 for(int j=0;j<len&&pri[j]*i<maxn;j++){ 55 no_Pri[pri[j]*i]=true; 56 if(i%pri[j]==0)break; 57 } 58 } 59 } 60 int main(){ 61 CalPri(); 62 int n; 63 scanf("%d",&n); 64 dij.n=n+42; 65 dij.dijkstra(1); 66 printf("%d\\n",dij.d[n]); 67 return 0; 68 }
以上是关于51nod 1693 水群(Dijkstra)的主要内容,如果未能解决你的问题,请参考以下文章