[数据生成器]UVA10054 The Necklace
应吴老师之邀,写了个数据生成器。
目前这个数据生成器可以保证生成的数据都是合法的,且效率也还不错。只是在建立普通连通图的时候zyy偷懒了,直接把所有点串起来从而保证图的连通。如果有大神有更好的方法请不吝指教,zyy不胜感谢~~
下面是代码:
1 #include<cstdio> 2 #include<ctime> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<vector> 7 using namespace std; 8 #define MAXN 40 9 #define MAXM 100 10 11 int A[MAXN+10][MAXN+10]; 12 int d[MAXN+10]; 13 14 int n, m; 15 16 int GetRand(int L, int R) 17 { 18 int Len = R - L + 1; 19 int Ret = rand() * rand() % Len + L; 20 return Ret; 21 } 22 23 inline void Addedge(int u,int v,int o) 24 { 25 A[u][v]+=o;A[v][u]+=o; 26 d[u]+=o;d[v]+=o; 27 m+=o; 28 } 29 30 void gen() 31 { 32 int i, j, k, t; 33 bool Again; 34 memset(A, 0, sizeof(A)); 35 memset(d, 0, sizeof(d)); 36 for(i=1;i<n;i++)//保证图的连通 37 { 38 A[i][i+1]++;A[i+1][i]++; 39 d[i]++;d[i+1]++; 40 } 41 for(i=1;i<=m-n+1;i++)//剩下的边随机连接 42 { 43 do{ 44 j=GetRand(1,n); 45 k=GetRand(1,n); 46 if(j==k) continue; 47 A[j][k]++;A[k][j]++; 48 d[j]++;d[k]++; 49 break; 50 }while(true); 51 } 52 //调整边,使所有的顶点的度为偶数 53 for(i=1;i<=n;i++) 54 { 55 if(d[i]%2)//如果i点度为奇数,就再找一个度为奇数的点 56 { 57 for(j=i+1;j<=n;j++) 58 { 59 if(d[j]%2) 60 { 61 if(A[i][j])//i、j之间有边 62 { 63 if(d[i]!=1&&d[j]!=1)//i、j之间不止一条边,则删掉一条边 64 { 65 Addedge(i,j,-1); 66 break; 67 } 68 else 69 { 70 continue; 71 } 72 } 73 else//i、j之间没有边,则连接i、j 74 { 75 Addedge(i,j,1); 76 break; 77 } 78 } 79 } 80 if(j>n) 81 { 82 for(k=i+1;k<=n;k++) 83 { 84 if(d[k]) 85 break; 86 } 87 t=k;//找一个度为奇数的顶点t 88 for(k=1;k<i;k++)//再找一个度为偶数的顶点k,若k与i、t不相连,则连接tk、ik 89 { 90 if(!A[t][k]&&!A[k][i]) 91 { 92 Addedge(t,k,1); 93 Addedge(i,k,1); 94 break; 95 } 96 } 97 Again=false; 98 if(k>=i)//需要重新调整 99 { 100 for(t=1;t<=n;t++)//连接i与任意一个不相连的顶点t 101 { 102 if(!A[t][i]&&i!=t) 103 { 104 Addedge(t,i,1); 105 Again=true; 106 break; 107 } 108 } 109 if(t>n)//如果找不到这样的t,在确保图的连通的条件下删掉一条边 110 { 111 for(t=1;t<=n;t++) 112 { 113 if(d[t]>1) 114 { 115 Addedge(t,i,-1); 116 Again=true; 117 break; 118 } 119 } 120 } 121 } 122 if(Again) 123 i=0; 124 } 125 } 126 } 127 } 128 129 130 int main() 131 { 132 //freopen("data4.in","w",stdout); 133 srand(time(NULL)); 134 int cas =10000;//GetRand(1, 1); 135 int i,j; 136 printf("%d\n", cas); 137 while(cas-- > 0) 138 { 139 n = GetRand(MAXN/5*3, MAXN); 140 m = GetRand(MAXM/5*3, MAXM); 141 gen(); 142 printf("%d\n", m); 143 for(i=1;i<n;i++) 144 for(j=i+1;j<=n;j++) 145 while(A[i][j]-->0) 146 printf("%d %d\n",i,j); 147 } 148 return 0; 149 }