Build Roads
生活随笔
收集整理的這篇文章主要介紹了
Build Roads
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Build Roads
題意:
n個點,每個點的值為a[i],求最小生成樹
a[i]是通過題目中給出的程序得到(即a[i]如何得到的我們并不需要很了解)
題解:
肯定不能直接跑最小生成樹,因為數據太大了
銀川也有個類似的題,比賽時我直接打表,發現當n很大時,答案就是n-1,通過我大量枚舉,我得到結論,當n>1000時,我們就直接套結論,當小于1000時,就跑遍最小生成樹
但是忘了一種情況,導致一直wa,題目給的L和R,表示的是a[i]的范圍,如果L == R時(n很大),說明每個點的值都是L,那么gcd求出邊長都是L,所以答案就是(n-1)*L
挺可惜,比賽時一直沒想到最后這一小點
代碼:
//蒟蒻三人行 #include<bits/stdc++.h> #include<map> #define random(a,b) ((a)+rand()%((b-a+1))) typedef long long ll; using namespace std; const int maxn=1e7+9; int n,L,R,a[200001]; int tot=0; unsigned long long seed; unsigned long long xorshift64() {unsigned long long x=seed;x^=x<<13;x^=x>>7;x^=x<<17;return seed=x; } int gen(){return xorshift64()%(R-L+1)+L; } int gcd(int a,int b) {if(b)return gcd(b,a%b);return a; } int fa[maxn]; struct node{int u,v,w; }edge[maxn]; bool cmp(node a,node b) {return a.w<b.w; } int find(int x) {if(fa[x]==-1)return x;else return fa[x]=find(fa[x]); } ll kruskal(int n) {memset(fa,-1,sizeof(fa));sort(edge+1,edge+1+tot,cmp);int cnt=0;ll ans=0;//cout<<tot<<endl;for(int i=1;i<=tot;i++){int u=edge[i].u;int v=edge[i].v;int w=edge[i].w;int fu=find(u);int fv=find(v);if(fu!=fv){ans+=w;fa[fu]=fv;cnt++;}//cout<<n<<" "<<cnt<<endl;if(cnt==n-1){//cout<<cnt<<endl;break;}}//cout<<tot<<endl;return ans; } void add(int u,int v,int w) {edge[++tot].u=u;edge[tot].v=v;edge[tot].w=w; } int main() { // cout<<gcd(4,6);//srand(time(0));//int t=1000; // while(t--)// n=random(1,100000);// L=random(1,19999);// R=random(L,200000);// seed=(unsigned long long)random(1,10000000000000); scanf("%d%d%d%llu",&n,&L,&R,&seed);// printf("生成數據%d %d %d %llu\n",n,L,R,seed);memset(edge,0,sizeof(node));memset(a,0,sizeof(int));for(int i=1;i<=n;i++){a[i]=gen();//printf("a[%d]=%d\n",i,a[i]);//2464638799566668449} tot=0;if(L==R){cout<<1ll*(n-1)*L<<endl;return 0;} if(n>1000){cout<<(n-1)<<endl;return 0;}for(int i=1;i<=n;i++){//printf("a[%d]=%d\n",i,a[i]);for(int j=i+1;j<=n;j++){int w=gcd(a[i],a[j]);// printf("i=%d j=%d w=%d\n",i,j,w);// printf("w=%d\n",w);add(i,j,w);add(j,i,w);}}//cout<<tot<<endl;// cout<<edge[1].w;int ww=kruskal(n);cout<<ww<<endl; // if(ww!=n-1) // { // cout<<"錯誤"<<endl; // //printf("最終%d %d %d %llu\n",n,L,R,seed); // //cout<<"答案= "<<ww<<endl; // // } // else cout<<"正確"<<endl;//cout<<"答案= "<<ww<<endl;return 0; }/* 50000 16199 18966 29398 */總結
以上是生活随笔為你收集整理的Build Roads的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 圣诞贺卡怎么做简单又漂亮 步骤是什么
- 下一篇: 芈月传演员表介绍 芈月传主要演员介绍