http://codeforces.com/contest/265/problem/D
好题呀
先按照求素数的方法 再求的过程中 把所给数组中具有相同素数约数的最邻近的两个数 进行建边 然后进行拓扑
代码及其注释:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<algorithm> #include<cmath> #define LL long long #define sint short int //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N=100005; const int INF=0x3f3f3f3f; //typedef pair<int,int>point; int head[N],I; struct node { int j,next; }side[N*100]; bool prime[N],a[N]; int dist[N],t[N]; queue<int>qt; void add(int i,int j) { side[I].j=j; side[I].next=head[i]; head[i]=I++; } void build() { memset(prime,true,sizeof(prime)); for(int i=2;i<N;++i) { if(prime[i]) { int pr=-1; if(a[i]) pr=i; for(int j=i*2;j<N;j=j+i) { prime[j]=false; if(a[j]) { if(pr==-1) {pr=j;continue;} add(pr,j); //pr 和 j 是给定的数,在具有相同约数 i 的情况下邻近 所以建边 ++t[j];//拓扑标记 pr=j; } } } } } int topology() { for(int i=0;i<N;++i) if(a[i]&&t[i]==0) {qt.push(i);dist[i]=1;} int ans=1; while(!qt.empty()) { int x=qt.front();qt.pop(); for(int w=head[x];w!=-1;w=side[w].next) { int j=side[w].j; --t[j]; if(t[j]==0) { dist[j]=dist[x]+1;//最后更新的一定是最长的一条路径 ans=dist[j];//更新答案 qt.push(j); } } } return ans; } int main() { //freopen("data.in","r",stdin); int n; while(scanf("%d",&n)!=EOF) { memset(a,false,sizeof(a)); for(int i=0;i<n;++i) { int k; scanf("%d",&k); a[k]=true; } memset(head,-1,sizeof(head)); I=0; memset(t,0,sizeof(t)); build(); memset(dist,0,sizeof(dist)); printf("%d\n",topology()); } return 0; }