新的一个月 ><
11.1
做了个cf .... 还是很菜诶...
读题不仔细,还有就是 还在犯数组开小的错误....(改了半小时才发现..)
cf 378c C - Epidemic in Monstropolis
还是不会写这种有点繁琐的...也是不会写就不去写然后就更不会写了
倒着找,找出一段 [l,r] 的区间,从最大值开始合并,如果不能合并的话,就 NO 能够合并的话,就看是到 L 还是 到 R
一直到合并完,再检查下 a 数列的长度是不是变成 0 了
看了题解的代码
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 typedef long long LL; 9 const int maxn = 505; 10 LL a[maxn],b[maxn]; 11 int n,k; 12 13 void solve(){ 14 int tot = n; 15 vector<pair<int,char> > ans; 16 for(int j = k;j >= 1;j--){ 17 LL sum = 0LL; 18 int l,r; 19 for(int i = tot;i >= 1;i--){ 20 sum += a[i]; 21 if(sum >= b[j]) { 22 l = i; 23 break; 24 } 25 } 26 27 if(sum != b[j]){ 28 puts("NO"); 29 return; 30 } 31 32 r = tot; tot = l-1; 33 for(r;r > l;r--){ 34 int left = 0,right = 0,add,st; 35 LL mx = 0LL; 36 for(int pos = l;pos <= r;pos++){ 37 if(pos-1 >= l && a[pos] > a[pos-1]){ 38 if(a[pos] > mx){ 39 mx = a[pos]; 40 left = 1; 41 right = 0; 42 add = pos; 43 } 44 } 45 if(pos+1 <= r && a[pos] > a[pos+1]){ 46 if(a[pos] > mx){ 47 mx = a[pos]; 48 right = 1; 49 left = 0; 50 add = pos; 51 } 52 } 53 } 54 55 //printf("mx = %d left = %d right = %d add = %d\n",mx,left,right,add); 56 if(mx == 0){ 57 puts("NO"); 58 return; 59 } 60 if(left){ 61 a[add] += a[add-1]; 62 st = add; 63 ans.push_back(make_pair(add,'L')); 64 } 65 if(right){ 66 a[add] += a[add+1]; 67 st = add+2; 68 ans.push_back(make_pair(add,'R')); 69 } 70 71 for(int p = st;p <= r;p++) a[p-1] = a[p]; 72 } 73 } 74 if(tot !=0){ 75 puts("NO"); 76 return; 77 } 78 puts("YES"); 79 for(int i = 0;i < ans.size();i++) printf("%d %c\n",ans[i].first,ans[i].second); 80 } 81 82 int main(){ 83 while(scanf("%d",&n) != EOF){ 84 for(int i = 1;i <= n;i++) scanf("%I64d",&a[i]); 85 scanf("%d",&k); 86 for(int i = 1;i <= k;i++) scanf("%I64d",&b[i]); 87 solve(); 88 } 89 return 0; 90 }
11.2
hdu 5839 Special Tetrahedron
想想好像还没有三维几何板...于是去补下这题
给出 n 个点,求满足这两个条件的四面体的个数
至少有四条边相等
如果只有四条边相等的话,那么不相等的那两条边不相邻
可以把题目转化一下,在四面体中,每条边都只有一条边和它不相邻
所以 就 枚举 一个空间四边形的对角线,把到对角线两端的点距离相等的点都丢到一个 s 里面,再在这个 s 里面 n2 枚举,求四边相等的空间四边形的个数
因为 一个空间四边形的对角线有两条,所以会被计数两次
一个正四面体,可以画出 3 个空间四边形,每个空间四边形又被计数 2 次,所以是ans1/2 + ans2/6
判正面体写挫....改了一下午....wwwww
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<string> 6 #include<vector> 7 #include <ctime> 8 #include<queue> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<cmath> 13 14 typedef long long ll; 15 typedef unsigned long long ull; 16 #define INF (1ll<<60)-1 17 using namespace std; 18 const long double eps=1e-8; 19 #define zero(x) (((x)>0?(x):-(x))<eps) 20 struct point3{ 21 long double x,y,z; 22 point3(long double x=0,long double y=0,long double z=0):x(x),y(y),z(z){} 23 }; 24 typedef point3 vec3; 25 26 int dcmp(double x){ 27 if(fabs(x) < eps) return 0;else return x < 0 ? -1 : 1; 28 } 29 30 vec3 operator + (vec3 a,vec3 b){ 31 return vec3(a.x+b.x,a.y+b.y,a.z+b.z); 32 } 33 vec3 operator - (vec3 a,vec3 b){ 34 return vec3(a.x-b.x,a.y-b.y,a.z-b.z); 35 } 36 vec3 operator * (vec3 a,double p){ 37 return vec3(a.x*p,a.y*p,a.z*p); 38 } 39 vec3 operator / (vec3 a,double p){ 40 return vec3(a.x/p,a.y/p,a.z/p); 41 } 42 point3 operator * (point3 a,point3 b){ 43 return point3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); 44 } 45 struct line3{ 46 point3 a,b; 47 }; 48 struct plane3{ 49 point3 a,b,c; 50 }; 51 point3 xmult(point3 u,point3 v){ 52 point3 ret; 53 ret.x=u.y*v.z-v.y*u.z; 54 ret.y=u.z*v.x-u.x*v.z; 55 ret.z=u.x*v.y-u.y*v.x; 56 return ret; 57 } 58 double dmult(point3 u,point3 v){ 59 return u.x*v.x+u.y*v.y+u.z*v.z; 60 } 61 point3 subt(point3 u,point3 v){ 62 point3 ret; 63 ret.x=u.x-v.x; 64 ret.y=u.y-v.y; 65 ret.z=u.z-v.z; 66 return ret; 67 } 68 /*****四面体体积*********/ 69 double volume(point3 a, point3 b, point3 c, point3 d) { 70 return fabs(dmult( (b - a) * (c - a) , (d - a) ) ) / 6.0; 71 } 72 /*****平面法向量*********/ 73 point3 pvec(point3 s1,point3 s2,point3 s3){ 74 return xmult(subt(s1,s2),subt(s2,s3)); 75 } 76 /*****两点距离***********/ 77 double Distance(point3 p1,point3 p2){ 78 return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z); 79 } 80 /*****向量长度***********/ 81 double vlen(point3 p){ 82 return sqrt(p.x*p.x+p.y*p.y+p.z*p.z); 83 } 84 /*****点到平面距离***************/ 85 double ptoplane(point3 p,point3 s1,point3 s2,point3 s3){ 86 return fabs(dmult(pvec(s1,s2,s3),subt(p,s1)))/vlen(pvec(s1 ,s2,s3)); 87 } 88 /*****判四点共面*********/ 89 int dots_onplane(point3 a,point3 b,point3 c,point3 d){ 90 return zero(dmult(pvec(a,b,c),subt(d,a))); 91 } 92 /*****判三点共线*********/ 93 int dots_inline(point3 p1,point3 p2,point3 p3){ 94 return vlen(xmult(subt(p1,p2),subt(p2,p3)))<eps; 95 } 96 /*****点到平面的投影*****/ 97 point3 shade_ptoplane(point3 p, point3 a, point3 b, point3 c) { 98 point3 nor = (b - a) * (c - a); 99 point3 nor0 = ( nor * dmult(nor, p - a) ) / vlen(nor) / vlen(nor); 100 return (p - nor0); 101 } 102 /*****判两直线垂直*************************/ 103 int perpendicular(point3 u1,point3 u2,point3 v1,point3 v2){ 104 return zero(dmult(subt(u1,u2),subt(v1,v2))); 105 } 106 double Dot(point3 a,point3 b){ 107 return a.x*b.x+a.y*b.y+a.z*b.z; 108 } 109 double Length(point3 a){ 110 return sqrt(Dot(a,a)); 111 } 112 point3 Cross(point3 a,point3 b){ 113 return point3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); 114 } 115 double area2(point3 a,point3 b,point3 c){ 116 return Length(Cross(b-a,c-a))*0.5; 117 } 118 bool operator == (point3 a,point3 b){ 119 if(fabs(a.x-b.x)==0 && fabs(a.y-b.y)==0 && fabs(a.z-b.z)==0) 120 return true; 121 return false; 122 } 123 124 point3 p[505],s[505]; 125 int n; 126 127 void solve(){ 128 int ans1 = 0,ans2 = 0; 129 for(int i = 1;i <= n;i++){ 130 for(int j = i+1;j <=n;j++){ 131 int tot = 0; 132 for(int k = 1;k <= n;k++){ 133 double lb = Distance(p[k],p[i]); 134 double ub = Distance(p[k],p[j]); 135 // cout << "lb = " << lb << "ub = " << ub << "\n"; 136 if(fabs(lb-ub) <= eps){ 137 s[++tot] = p[k]; 138 } 139 } 140 141 for(int l = 1;l <= tot;l++){ 142 for(int r = l+1;r <= tot;r++){ 143 if(dots_onplane(p[i],p[j],s[l],s[r])){ 144 continue; 145 } 146 147 if(dcmp(Distance(s[l],p[i]) - Distance(s[r],p[j])) != 0) continue; 148 149 double lb = Distance(p[i],p[j]); 150 double ub = Distance(s[l],s[r]); 151 double mid = Distance(p[i],s[l]); 152 153 if(fabs(lb-ub) <= eps && fabs(ub-mid) <= eps) ans2++; 154 else ans1++; 155 } 156 } 157 } 158 } 159 // printf("ans1 = %d ans2 = %d\n",ans1,ans2); 160 printf("%d\n",ans1/2 + ans2/6); 161 } 162 163 int main(){ 164 int T,kase = 0; 165 scanf("%d",&T); 166 while(T--){ 167 scanf("%d",&n); 168 for(int i = 1;i <= n;i++) { 169 //scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].z); 170 cin >> p[i].x >> p[i].y >> p[i].z; 171 } 172 printf("Case #%d: ",++kase); 173 solve(); 174 } 175 return 0; 176 }
11.3
hdu 5942 Just a Math Problem
f(k) 为 k 的不同质因子的个数,g(k) = 2^f(k) ,求 sigma g(k) ,k 的范围 是 1 到 n
可以先把要求的转化 一下,g(k) 就是 gcd(p,q) = 1 ,并且 p*q == k 的对数,要求的 sigma 就是 gcd(p,q) = 1 并且 p*q <= n 的对数
先枚举 x 到 sqrt(n)
假设 x < y
可以先容斥 出 y 的数量,假设总的个数是 Y ,然后对于 每一个 x ,y 包含 了小于 x 和大于 x 的部分,需要 减去 小于 x 的个数
小于 x 并且 和 x 互质 的个数 为 phi(x) ,所以对于 每个 枚举 的 x ,对答案的贡献是 Y - phi(x)
需要预处理出 质因子出来
最后 ans*2 + 1 (x > y 的情况 ,还有 1 1 这对)
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 #include <set> 8 using namespace std; 9 10 typedef long long LL; 11 const int maxn = 1e6+5; 12 const int N = 1e6+3; 13 const long long mod = 1e9+7; 14 LL n; 15 vector<int> p[maxn]; 16 int b[30]; 17 vector<long long> bin[105]; 18 int phi[maxn]; 19 20 void eula(){ 21 for(int i=1;i<=N;i++) 22 phi[i] = i; 23 for(int i=2;i<=N;i++) 24 if(phi[i]==i) //如果phi[i]==i的话说明还没有进行过计算,为素数 25 //没有进行过计算,说明在当前i值之前(即比i小的数中)没有i的因数,所以i为素数 26 for(int j=i;j<=N;j+=i) 27 phi[j]=phi[j]/i*(i-1);//将非素数进行计算 28 } 29 30 void init(){ 31 for(int i = 0;i < maxn;i++) p[i].clear(); 32 for(int i = 1;i <= 1e6;i++){ 33 int y = i; 34 for(int j = 2;j*j <= i;j++){ 35 if(y%j == 0){ 36 int flag = 0; 37 while(y%j == 0){ 38 if(flag == 0){ 39 p[i].push_back(j); 40 flag = 1; 41 } 42 y = y/j; 43 } 44 } 45 } 46 if(y > 1) p[i].push_back(y); 47 } 48 } 49 50 LL work(LL x,LL y){ 51 if(x == 1) return y; 52 int m = p[x].size(); 53 for(int i = 0;i <= m;i++) bin[i].clear(); 54 memset(b,0,sizeof(b)); 55 for(int i = 0;i < 1<<m;i++){ 56 for(int j = 0;j < m;j++){ 57 if((1<<j) & i) b[j] = 1; 58 } 59 int cnt = 0; 60 LL ret = 1LL; 61 for(int j = 0;j < m;j++){ 62 if(b[j]){ 63 cnt++; 64 ret = ret*p[x][j]; 65 } 66 b[j] = 0; 67 } 68 bin[cnt].push_back(ret); 69 } 70 71 //printf("x = %I64d y = %I64d\n",x,y); 72 73 LL res = 1LL*y; 74 int flag = 0; 75 for(int i = 1;i <= m;i++){ 76 LL tmp = 0LL; 77 for(int j = 0;j < bin[i].size();j++){ 78 LL now = y/bin[i][j]; 79 if(flag == 0) tmp = (tmp - now + mod) % mod; 80 else tmp = (tmp + now) % mod; 81 } 82 res = (res+tmp) % mod; 83 flag = !flag; 84 } 85 return res; 86 } 87 88 void solve(){ 89 LL ans = 0LL; 90 for(int i = 1;1LL*i*i <= n;i++){ 91 LL r = n/(1LL*i); 92 LL tmp = work(i,r); 93 // printf("i = %d tmp = %I64d ",i,tmp); 94 tmp -= phi[i]; 95 ans = (ans + tmp) % mod; 96 // printf("tmp = %I64d\n",tmp); 97 } 98 ans = (ans*2LL + 1LL) % mod; 99 printf("%I64d\n",ans); 100 } 101 102 int main(){ 103 int T,kase = 0; 104 eula(); 105 init(); 106 scanf("%d",&T); 107 while(T--){ 108 scanf("%lld",&n); 109 printf("Case #%d: ",++kase); 110 solve(); 111 } 112 return 0; 113 }
hdu 1796 How many integers can you find
于是又去找了容斥来做
就是 上一题的容斥部分
看题就写...一写就跪
有两个要注意的地方,给出 的 pi 有可能 是 0 ,除 0 就 re 了,给出 的pi 没有说是素数,组合去算的时候要取下 lcm
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 typedef long long LL; 9 const int maxn = 1e5+5; 10 int n,m; 11 LL p[15],b[15],a[15]; 12 vector<long long> bin[15]; 13 14 LL gcd(LL a,LL b){ 15 return b == 0 ? a : gcd(b,a%b); 16 } 17 18 void solve(){ 19 memset(b,0,sizeof(b)); 20 for(int i = 0;i <= m;i++) bin[i].clear(); 21 for(int i = 0;i < (1<<m);i++){ 22 for(int j = 0;j < m;j++){ 23 if((1<<j) & i) b[j] = 1; 24 } 25 LL ret = 1LL; 26 int cnt = 0; 27 for(int j = 0;j < m;j++){ 28 if(b[j]){ 29 ret = 1LL*ret*p[j]/gcd(ret,p[j]); 30 b[j] = 0; 31 cnt++; 32 } 33 } 34 bin[cnt].push_back(ret); 35 } 36 37 int flag = 0; 38 n--; 39 LL ans = 1LL*n; 40 for(int i = 1;i <= m;i++){ 41 for(int j = 0;j < bin[i].size();j++){ 42 LL tmp = n/bin[i][j]; 43 //printf("i = %d bin[][] = %lld tmp = %lld\n",i,bin[i][j],tmp); 44 if(flag == 0) ans -= tmp; 45 else ans += tmp; 46 } 47 flag = !flag; 48 } 49 printf("%I64d\n",n-ans); 50 } 51 52 int main(){ 53 while(scanf("%d %d",&n,&m) != EOF){ 54 for(int i = 0;i < m;i++) scanf("%d",&a[i]); 55 int tot = 0; 56 for(int i = 0;i < m;i++){ 57 if(a[i] != 0) p[tot++] = a[i]; 58 } 59 m = tot; 60 solve(); 61 } 62 return 0; 63 }
发现好多是 dfs 去写的容斥
hdu 4135 Co-prime
呜呜呜.....今天才第一次写的说.... I am good vegetable
照这篇的改了下二进制枚举的写法
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 typedef long long LL; 9 const int maxn = 1e6+5; 10 LL l,r; 11 int n,m; 12 vector<int> p; 13 14 void Pre(){ 15 int y = n; 16 for(int j = 2;j*j <= n;j++){ 17 if(y%j == 0){ 18 p.push_back(j); 19 while(y%j == 0) y = y/j; 20 } 21 } 22 if(y > 1) p.push_back(y); 23 } 24 25 LL solve(LL x){ 26 if(x <= 1) return x; 27 LL res = 0LL; 28 for(int i = 1;i < (1<<m);i++){ 29 LL now = 1LL,cnt = 0LL; 30 for(int j = 0;j < m;j++){ 31 if((1<<j) & i){ 32 cnt++; 33 now = now * p[j]; 34 } 35 } 36 // printf("cnt = %d\n",cnt); 37 if(cnt&1) res += x/now; 38 else res -= x/now; 39 } 40 //printf("x = %I64d res = %I64d\n",x,res); 41 return x - res; 42 } 43 44 int main(){ 45 int T,kase = 0; 46 scanf("%d",&T); 47 while(T--){ 48 scanf("%lld %lld %d",&l,&r,&n); 49 p.clear(); 50 Pre(); 51 m = p.size(); 52 LL ans = solve(r) - solve(l-1); 53 printf("Case #%d: %I64d\n",++kase,ans); 54 } 55 return 0; 56 }
11.4
...
11.5
hdu 5961 传递
暴力水果..
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 2050; 9 vector<int> p[maxn]; 10 vector<int> q[maxn]; 11 int n,P[maxn][maxn],Q[maxn][maxn]; 12 char s[maxn]; 13 14 void solve(){ 15 for(int b = 1;b <= n;b++){ 16 for(int a = 1;a <= n;a++){ 17 if(P[a][b] == 0) continue; 18 for(int j = 0;j < p[b].size();j++){ 19 int c = p[b][j]; 20 if(P[b][c] == 1 && P[a][c] != 1){ 21 puts("N"); 22 return; 23 } 24 } 25 } 26 } 27 28 for(int b = 1;b <= n;b++){ 29 for(int a = 1;a <= n;a++){ 30 if(Q[a][b] == 0) continue; 31 for(int j = 0;j < q[b].size();j++){ 32 int c = q[b][j]; 33 if(Q[b][c] == 1 && Q[a][c] != 1){ 34 puts("N"); 35 return; 36 } 37 } 38 } 39 } 40 puts("T"); 41 } 42 43 int main(){ 44 int T; 45 scanf("%d",&T); 46 while(T--){ 47 scanf("%d",&n); 48 for(int i = 1;i <= n;i++) p[i].clear(),q[i].clear(); 49 memset(P,0,sizeof(P)); 50 memset(Q,0,sizeof(Q)); 51 for(int i = 1;i <= n;i++){ 52 scanf("%s",s+1); 53 for(int j = 1;j <= n;j++){ 54 if(s[j] == 'P'){ 55 p[i].push_back(j); 56 P[i][j] = 1; 57 } 58 if(s[j] == 'Q'){ 59 q[i].push_back(j); 60 Q[i][j] = 1; 61 } 62 } 63 } 64 solve(); 65 } 66 return 0; 67 }
11.6
hdu 5964 平行四边形
推出那个柿子..再O(n) 扫一遍...话说多一个for循环都被T
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 #include <set> 7 using namespace std; 8 9 typedef long long LL; 10 const long long INF = 1e17; 11 LL a,b,c,d; 12 int n; 13 14 LL F(LL xx,LL yy){ 15 LL res = a*c*xx*xx + b*d*yy*yy + (a*d + b*c)*xx*yy; 16 return res; 17 } 18 19 int main(){ 20 while(scanf("%lld %lld %lld %lld",&a,&b,&c,&d) != EOF){ 21 scanf("%d",&n); 22 LL x,y; 23 LL mx = 0,mn = INF; 24 //printf("mx = %lld mn = %lld\n",mx,mn); 25 for(int i = 1;i <= n;i++){ 26 scanf("%lld %lld",&x,&y); 27 mx = max(mx,F(x,y)); 28 mn = min(mn,F(x,y)); 29 //scan(x[i]); 30 //scan(y[i]); 31 } 32 //printf("mx = %lld mn = %lld\n",mx,mn); 33 double res = fabs(1.0*(mx-mn)/(a*d-b*c)); 34 //cout << res; 35 printf("%lld\n",(long long)(res+0.5)); 36 37 } 38 return 0; 39 }
hdu 5973 Game of Taking Stones
裸的威佐夫...但是java 不熟...而且 根号5精度不够...wa成狗
1 import java.io.*; 2 import java.util.*; 3 import java.text.*; 4 import java.math.BigDecimal; 5 import java.math.BigInteger; 6 import java.math.MathContext; 7 import java.math.RoundingMode; 8 9 public class Main{ 10 public static void main(String args[]){ 11 Scanner in = new Scanner(System.in); 12 while(in.hasNext()){ 13 BigInteger a = in.nextBigInteger(); 14 BigInteger b = in.nextBigInteger(); 15 16 if(a.compareTo(b) == 1) { 17 BigInteger tmp; 18 tmp = a; 19 a = b; 20 b = tmp; 21 } 22 23 BigDecimal num = new BigDecimal("2.2360679774997896964091736687312762354406183596115257242708972454105209256378048994144144083787822749"); 24 25 // MathContext mc = new MathContext(100,RoundingMode.HALF_DOWN); 26 27 // BigDecimal phi = new BigDecimal(Math.sqrt(num.doubleValue()) ,mc); 28 BigDecimal phi; 29 BigDecimal half = new BigDecimal(0.5); 30 BigDecimal one = new BigDecimal(1); 31 phi = num.add(one); 32 phi = phi.multiply(half); 33 34 //System.out.println(phi); 35 36 BigInteger c = b.subtract(a); 37 String tmp = c.toString(); 38 BigDecimal cheng = new BigDecimal(tmp); 39 BigDecimal t = phi.multiply(cheng); 40 41 //t = t.setScale(0, BigDecimal.ROUND_DOWN); 42 43 BigInteger A = t.toBigInteger(); 44 //BigInteger AA = a.toBigInteger(); 45 46 if(A.compareTo(a) == 0){ 47 System.out.println("0"); 48 } 49 else System.out.println("1"); 50 } 51 in.close(); 52 } 53 }
11.7
LA 6955 Finding Lines
给出 n 个点,再给出一个概率 p ,问是否有这样的一条直线存在,满足在直线上的点的个数大于等于n*p向上取整
n 的范围 是 1e5
-------------------------
看知乎的时候有人在说随机过的题说到了这个
把枚举直线 弄成 rand 出直线...
可是,一直蛙...搜了别人ac代码交也蛙
放这儿先....
1 #include <cstdio> 2 #include <cstring> 3 #include <ctime> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 typedef long long LL; 10 const int maxn = 1e5+5; 11 int n,p; 12 int x[maxn],y[maxn]; 13 14 int on(int a,int b,int c){ 15 int X1 = x[b] - x[a]; 16 int Y1 = y[b] - y[a]; 17 int X2 = x[c] - x[a]; 18 int Y2 = y[c] - y[a]; 19 return 1LL*X1*Y2 - 1LL*X2*Y1 == 0LL; 20 } 21 22 void solve(){ 23 if(n == 1 || n == 2){ 24 puts("possible"); 25 return; 26 } 27 srand(time(NULL)); 28 //int tot = ceil(1.0*p*n/100.0); 29 //printf("tot = %d\n",tot); 30 for(int i = 1;i <= 3000;i++){ 31 int u = rand() % n + 1; 32 int v = rand() % n + 1; 33 if(u == v) continue; 34 int cnt = 0; 35 for(int j = 1;j <= n;j++){ 36 if(on(j,u,v)) cnt++; 37 } 38 if(cnt*100 >= p*n){ 39 puts("possible"); 40 return; 41 } 42 } 43 puts("impossible"); 44 } 45 46 47 int main(){ 48 while(scanf("%d %d",&n,&p) != EOF){ 49 for(int i = 1;i <= n;i++) scanf("%d %d",&x[i],&y[i]); 50 solve(); 51 } 52 return 0; 53 }
11.8
不懂
11.9
不知道该干嘛,写写几何题练下手叭
uva 11437 Triangle Fun
给出一个三角形,里面有线相交,求里面相交出来的小三角形的面积
这里求一条直线的时候,因为有比例关系,用向量来算更方便些
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <vector> 5 using namespace std; 6 //lrj计算几何模板 7 8 typedef long long LL; 9 10 struct Point 11 { 12 double x, y; 13 Point(double x=0, double y=0) :x(x),y(y) {} 14 }; 15 typedef Point Vector; 16 17 Point read_point(void) 18 { 19 double x, y; 20 scanf("%lf%lf", &x, &y); 21 return Point(x, y); 22 } 23 24 const double EPS = 1e-10; 25 26 //向量+向量=向量 点+向量=点 27 Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); } 28 29 //向量-向量=向量 点-点=向量 30 Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); } 31 32 //向量*数=向量 33 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 34 35 //向量/数=向量 36 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 37 38 bool operator < (const Point& a, const Point& b) 39 { return a.x < b.x || (a.x == b.x && a.y < b.y); } 40 41 int dcmp(double x) 42 { if(fabs(x) < EPS) return 0; else return x < 0 ? -1 : 1; } 43 44 bool operator == (const Point& a, const Point& b) 45 { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; } 46 47 /**********************基本运算**********************/ 48 49 //点积 50 double Dot(Vector A, Vector B) 51 { return A.x*B.x + A.y*B.y; } 52 //向量的模 53 double Length(Vector A) { return sqrt(Dot(A, A)); } 54 55 //向量的夹角,返回值为弧度 56 double Angle(Vector A, Vector B) 57 { return acos(Dot(A, B) / Length(A) / Length(B)); } 58 59 //叉积 60 double Cross(Vector A, Vector B) 61 { return A.x*B.y - A.y*B.x; } 62 63 //向量AB叉乘AC的有向面积 64 double Area2(Point A, Point B, Point C) 65 { return Cross(B-A, C-A); } 66 67 //向量A旋转rad弧度 68 Vector VRotate(Vector A, double rad) 69 { 70 return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad)); 71 } 72 73 //将B点绕A点旋转rad弧度 74 Point PRotate(Point A, Point B, double rad) 75 { 76 return A + VRotate(B-A, rad); 77 } 78 79 //求向量A向左旋转90°的单位法向量,调用前确保A不是零向量 80 Vector Normal(Vector A) 81 { 82 double l = Length(A); 83 return Vector(-A.y/l, A.x/l); 84 } 85 86 /**********************点和直线**********************/ 87 88 //求直线P + tv 和 Q + tw的交点,调用前要确保两条直线有唯一交点 89 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) 90 { 91 Vector u = P - Q; 92 double t = Cross(w, u) / Cross(v, w); 93 return P + v*t; 94 }//在精度要求极高的情况下,可以自定义分数类 95 96 //P点到直线AB的距离 97 double DistanceToLine(Point P, Point A, Point B) 98 { 99 Vector v1 = B - A, v2 = P - A; 100 return fabs(Cross(v1, v2)) / Length(v1); //不加绝对值是有向距离 101 } 102 103 //点到线段的距离 104 double DistanceToSegment(Point P, Point A, Point B) 105 { 106 if(A == B) return Length(P - A); 107 Vector v1 = B - A, v2 = P - A, v3 = P - B; 108 if(dcmp(Dot(v1, v2)) < 0) return Length(v2); 109 else if(dcmp(Dot(v1, v3)) > 0) return Length(v3); 110 else return fabs(Cross(v1, v2)) / Length(v1); 111 } 112 113 //点在直线上的射影 114 Point GetLineProjection(Point P, Point A, Point B) 115 { 116 Vector v = B - A; 117 return A + v * (Dot(v, P - A) / Dot(v, v)); 118 } 119 120 //线段“规范”相交判定 121 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 122 { 123 double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1); 124 double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1); 125 return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; 126 } 127 128 //判断点是否在线段上 129 bool OnSegment(Point P, Point a1, Point a2) 130 { 131 Vector v1 = a1 - P, v2 = a2 - P; 132 return dcmp(Cross(v1, v2)) == 0 && dcmp(Dot(v1, v2)) < 0; 133 } 134 135 Point A,B,C,D,E,F,P,Q,R; 136 137 void solve(){ 138 Vector CF = Vector(A-C + (B-A)/3.0); 139 Vector AD = Vector(B-A + (C-B)/3.0); 140 Vector BE = Vector(C-B + (A-C)/3.0); 141 142 P = GetLineIntersection(A,AD,B,BE); 143 Q = GetLineIntersection(B,BE,C,CF); 144 R = GetLineIntersection(C,CF,A,AD); 145 146 /* printf("P.x = %lf P.y = %lf\n",P.x,P.y); 147 printf("Q.x = %lf Q.y = %lf\n",Q.x,Q.y); 148 printf("R.x = %lf R.y = %lf\n",R.x,R.y);*/ 149 150 double ans = Cross(Q-R,P-R); 151 printf("%.0lf\n",fabs(ans)*0.5); 152 } 153 154 int main(){ 155 int T; 156 scanf("%d",&T); 157 while(T--){ 158 scanf("%lf %lf %lf %lf %lf %lf",&A.x,&A.y,&B.x,&B.y,&C.x,&C.y); 159 solve(); 160 } 161 return 0; 162 }
uva 11646 Athletics Track
最开始以为是普通的跑道那样的形状,列不出方程来算半径...后来发现是一个同心圆
atan(x) 的返回值 是(-pi/2,pi/2)
atan2(y,x) 的返回值 是 (-pi,pi)
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int a,b; 9 10 void solve(){ 11 double al = atan2(1.0*b,1.0*a); 12 double bl = 2.0*al; 13 double r = 200.0 / (2.0*cos(al) + bl); 14 15 double aa = r * sin(al); 16 double bb = r * cos(al); 17 18 printf("%.12f %.12f\n",2.0*bb,2.0*aa); 19 } 20 21 int main(){ 22 int kase = 0; 23 char s[10]; 24 while(scanf("%d%s%d",&a,s,&b) != EOF){ 25 printf("Case %d: ",++kase); 26 solve(); 27 } 28 return 0; 29 }
uva 11817 Tunnelling the Earth
球面上两点的球面距离 和 直线距离
手算不出公式...公式
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 const double pi = acos(-1.0); 9 double R,W1,W2,J1,J2; 10 11 void solve(){ 12 double al = sin(W1) * sin(W2) + cos(W1)*cos(W2)*cos(J1-J2); 13 double d = R * acos(al); 14 double D = 2.0 *R* sin(d/(2.0*R)); 15 printf("%.0f\n",d-D); 16 } 17 18 int main(){ 19 int T; 20 R = 6371009.0; 21 scanf("%d",&T); 22 while(T--){ 23 scanf("%lf %lf %lf %lf",&W1,&J1,&W2,&J2); 24 W1 = W1*pi/180.0; 25 J1 = J1*pi/180.0; 26 W2 = W2*pi/180.0; 27 J2 = J2*pi/180.0; 28 solve(); 29 } 30 return 0; 31 }
11.10
poj 1222 EXTENDED LIGHTS OUT
高斯消元解异或方程组
先存个板子...不知道这个板好不好,多试几道题先.
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAXN = 40; 8 //有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var 9 int equ, var; 10 int a[MAXN][MAXN]; //增广矩阵 11 int x[MAXN]; //解集 12 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用) 13 int free_num;//自由变元的个数 14 15 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数 16 int Gauss() { 17 int max_r, col, k; 18 free_num = 0; 19 for (k = 0, col = 0; k <equ&& col <var; k++, col++) { 20 max_r = k; 21 for (int i = k + 1; i<equ; i++) { 22 if (abs(a[i][col]) > abs(a[max_r][col])) 23 max_r = i; 24 } 25 if (a[max_r][col] == 0) { 26 k--; 27 free_x[free_num++] = col;//这个是自由变元 28 continue; 29 } 30 if (max_r != k) { 31 for (int j = col; j < var + 1; j++) 32 swap(a[k][j], a[max_r][j]); 33 } 34 for (int i = k + 1; i<equ; i++) { 35 if (a[i][col] != 0) { 36 for (int j = col; j < var + 1; j++) 37 a[i][j] ^= a[k][j]; 38 } 39 } 40 } 41 for (int i = k; i<equ; i++) 42 if (a[i][col] != 0) 43 return -1;//无解 44 if (k <var) return var - k;//自由变元个数 45 //唯一解,回代 46 47 for (int i = var - 1; i >= 0; i--) { 48 x[i] = a[i][var]; 49 for (int j = i + 1; j <var; j++) 50 x[i] ^= (a[i][j] && x[j]); 51 } 52 return 0; 53 } 54 55 int t[MAXN][MAXN]; 56 int dir[5][2] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; 57 58 void init(){ 59 memset(t, 0, sizeof(t)); 60 for (int i = 0; i < 5; ++i){ 61 for (int j = 0; j < 6; ++j){ 62 for (int k = 0; k < 5; ++k){ 63 int a = i + dir[k][0]; 64 int b = j + dir[k][1]; 65 if (a >= 0 && b >= 0 && a < 5 && b < 6){ 66 t[6 * i + j][6 * a + b] = 1; 67 } 68 } 69 } 70 } 71 } 72 73 int main(){ 74 init(); 75 int T,kase = 0; 76 scanf("%d", &T); 77 while(T--){ 78 memcpy(a, t, sizeof(a)); 79 for (int i = 0; i < 30; ++i) { 80 scanf("%d", &a[i][30]); 81 } 82 printf("PUZZLE #%d\n", ++kase); 83 equ = 30; 84 var = 30; 85 if (Gauss() == 0) { 86 for (int i = 0; i < 30; ++i) { 87 if (i % 6 == 5) { 88 printf("%d\n", x[i]); 89 } 90 else { 91 printf("%d ", x[i]); 92 } 93 } 94 } 95 } 96 return 0; 97 }
整型高斯消元板
抄的kuangbin的,线代书上找了几个方程组来算好像还是对的
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<math.h> 6 using namespace std; 7 8 const int MAXN=50; 9 10 11 12 int a[MAXN][MAXN];//增广矩阵 13 int x[MAXN];//解集 14 bool free_x[MAXN];//标记是否是不确定的变元 15 16 17 /* 18 void Debug(void) 19 { 20 int i, j; 21 for (i = 0; i < equ; i++) 22 { 23 for (j = 0; j < var + 1; j++) 24 { 25 cout << a[i][j] << " "; 26 } 27 cout << endl; 28 } 29 cout << endl; 30 } 31 */ 32 33 34 inline int gcd(int a,int b) 35 { 36 int t; 37 while(b!=0) 38 { 39 t=b; 40 b=a%b; 41 a=t; 42 } 43 return a; 44 } 45 inline int lcm(int a,int b) 46 { 47 return a/gcd(a,b)*b;//先除后乘防溢出 48 } 49 50 // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解, 51 //-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数) 52 //有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var. 53 int Gauss(int equ,int var) 54 { 55 int i,j,k; 56 int max_r;// 当前这列绝对值最大的行. 57 int col;//当前处理的列 58 int ta,tb; 59 int LCM; 60 int temp; 61 int free_x_num; 62 int free_index; 63 64 for(int i=0;i<=var;i++) 65 { 66 x[i]=0; 67 free_x[i]=true; 68 } 69 70 //转换为阶梯阵. 71 col=0; // 当前处理的列 72 for(k = 0;k < equ && col < var;k++,col++) 73 {// 枚举当前处理的行. 74 // 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差) 75 max_r=k; 76 for(i=k+1;i<equ;i++) 77 { 78 if(abs(a[i][col])>abs(a[max_r][col])) max_r=i; 79 } 80 if(max_r!=k) 81 {// 与第k行交换. 82 for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]); 83 } 84 if(a[k][col]==0) 85 {// 说明该col列第k行以下全是0了,则处理当前行的下一列. 86 k--; 87 continue; 88 } 89 for(i=k+1;i<equ;i++) 90 {// 枚举要删去的行. 91 if(a[i][col]!=0) 92 { 93 LCM = lcm(abs(a[i][col]),abs(a[k][col])); 94 ta = LCM/abs(a[i][col]); 95 tb = LCM/abs(a[k][col]); 96 if(a[i][col]*a[k][col]<0)tb=-tb;//异号的情况是相加 97 for(j=col;j<var+1;j++) 98 { 99 a[i][j] = a[i][j]*ta-a[k][j]*tb; 100 } 101 } 102 } 103 } 104 105 // Debug(); 106 107 // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0). 108 for (i = k; i < equ; i++) 109 { // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换. 110 if (a[i][col] != 0) return -1; 111 } 112 // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵. 113 // 且出现的行数即为自由变元的个数. 114 if (k < var) 115 { 116 // 首先,自由变元有var - k个,即不确定的变元至少有var - k个. 117 for (i = k - 1; i >= 0; i--) 118 { 119 // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行. 120 // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的. 121 free_x_num = 0; // 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元. 122 for (j = 0; j < var; j++) 123 { 124 if (a[i][j] != 0 && free_x[j]) free_x_num++, free_index = j; 125 } 126 if (free_x_num > 1) continue; // 无法求解出确定的变元. 127 // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的. 128 temp = a[i][var]; 129 for (j = 0; j < var; j++) 130 { 131 if (a[i][j] != 0 && j != free_index) temp -= a[i][j] * x[j]; 132 } 133 x[free_index] = temp / a[i][free_index]; // 求出该变元. 134 free_x[free_index] = 0; // 该变元是确定的. 135 } 136 return var - k; // 自由变元有var - k个. 137 } 138 // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵. 139 // 计算出Xn-1, Xn-2 ... X0. 140 for (i = var - 1; i >= 0; i--) 141 { 142 temp = a[i][var]; 143 for (j = i + 1; j < var; j++) 144 { 145 if (a[i][j] != 0) temp -= a[i][j] * x[j]; 146 } 147 if (temp % a[i][i] != 0) return -2; // 说明有浮点数解,但无整数解. 148 x[i] = temp / a[i][i]; 149 } 150 return 0; 151 } 152 int main(void) 153 { 154 // freopen("in.txt", "r", stdin); 155 // freopen("out.txt","w",stdout); 156 int i, j; 157 int equ,var; 158 while (scanf("%d %d", &equ, &var) != EOF) 159 { 160 memset(a, 0, sizeof(a)); 161 for (i = 0; i < equ; i++) 162 { 163 for (j = 0; j < var + 1; j++) 164 { 165 scanf("%d", &a[i][j]); 166 } 167 } 168 // Debug(); 169 int free_num = Gauss(equ,var); 170 if (free_num == -1) printf("无解!\n"); 171 else if (free_num == -2) printf("有浮点数解,无整数解!\n"); 172 else if (free_num > 0) 173 { 174 printf("-----------无穷多解! 自由变元个数为%d\n", free_num); 175 for (i = 0; i < var; i++) 176 { 177 if (free_x[i]) printf("x%d 是不确定的\n", i + 1); 178 else printf("x%d: %d\n", i + 1, x[i]); 179 } 180 } 181 else 182 { 183 for (i = 0; i < var; i++) 184 { 185 printf("x%d: %d\n", i + 1, x[i]); 186 } 187 } 188 printf("\n"); 189 } 190 return 0; 191 }
浮点型高斯消元板
抄的这个
感觉还需要多验证一下
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string.h> 5 #include <cmath> 6 #include <iomanip> 7 #include <algorithm> 8 using namespace std; 9 10 ///浮点型高斯消元模板 11 const double eps = 1e-12; 12 const int maxm = 1005;///m个方程,n个变量,输入就是m行n+1列 13 const int maxn = 1005; 14 int m,n; 15 double a[maxm][maxn+1];///增广矩阵 16 bool free_x[maxn];///判断是否是不确定的变元 17 double x[maxn];///解集 18 19 int sign(double x){ 20 return (x>eps)-(x<-eps); 21 } 22 23 /**返回值: 24 -1 无解 25 0 有且仅有一个解 26 >=1 有多个解,根据free_x判断哪些是不确定的解 27 */ 28 29 int Gauss() 30 { 31 int i,j; 32 int row,col,max_r; 33 m=n;///n个方程,n个变量的那种情况 34 for(row=0,col=0;row<m&&col<n;row++,col++) 35 { 36 max_r=row; 37 for(i=row+1;i<m;i++)///找到当前列所有行中的最大值(做除法时减小误差) 38 { 39 if(sign(fabs(a[i][col])-fabs(a[max_r][col]))>0) 40 max_r=i; 41 } 42 if(max_r!=row) 43 { 44 for(j=row;j<n+1;j++) 45 swap(a[max_r][j],a[row][j]); 46 } 47 if(sign(a[row][col])==0)///当前列row行以下全为0(包括row行) 48 { 49 row--; 50 continue; 51 } 52 for(i=row+1;i<m;i++) 53 { 54 if(sign(a[i][col])==0) 55 continue; 56 double tmp=a[i][col]/a[row][col]; 57 for(j=col;j<n+1;j++) 58 a[i][j]-=a[row][j]*tmp; 59 } 60 } 61 for(i=row;i<m;i++)///col=n存在0...0,a的情况,无解 62 { 63 if(sign(a[i][col])) 64 return -1; 65 } 66 if(row<n)///存在0...0,0的情况,有多个解,自由变元个数为n-row个 67 { 68 for(i=row-1;i>=0;i--) 69 { 70 int free_num=0;///自由变元的个数 71 int free_index;///自由变元的序号 72 for(j=0;j<n;j++) 73 { 74 if(sign(a[i][j])!=0&&free_x[j]) 75 free_num++,free_index=j; 76 } 77 if(free_num>1) 78 continue;///该行中的不确定的变元的个数超过1个,无法求解,它们仍然为不确定的变元 79 ///只有一个不确定的变元free_index,可以求解出该变元,且该变元是确定的 80 double tmp=a[i][n]; 81 for(j=0;j<n;j++) 82 { 83 if(sign(a[i][j])!=0&&j!=free_index) 84 tmp-=a[i][j]*x[j]; 85 } 86 x[free_index]=tmp/a[i][free_index]; 87 free_x[free_index]=false; 88 } 89 return n-row; 90 } 91 ///有且仅有一个解,严格的上三角矩阵(n==m) 92 for(i=n-1;i>=0;i--) 93 { 94 double tmp=a[i][n]; 95 for(j=i+1;j<n;j++) 96 if(sign(a[i][j])!=0) 97 tmp-=a[i][j]*x[j]; 98 x[i]=tmp/a[i][i]; 99 } 100 return 0; 101 }///模板结束 102 103 int main(){ 104 while(scanf("%d %d",&m,&n) != EOF){ 105 for(int i = 0;i < m;i++){ 106 for(int j = 0;j <=n;j++) scanf("%lf",&a[i][j]); 107 } 108 109 int res = Gauss(); 110 printf("res = %d\n",res); 111 for(int i = 0;i < n;i++) printf("x[%d] = %lf\n",i,x[i]); 112 113 } 114 return 0; 115 }
------浮点的这个有问题..
11.11 --- 11.17
有点遗憾诶...
幸运女神没有站在我们这边的话,那就再多些努力好了...可是已经走到大学的尽头没有努力的机会了呢
明年一定会更棒!
诶....每次打完比赛都要缓好一阵才缓的过来...
-------------- 昏割线 -------------
可以玩泥巴,写写代码,画画,学点儿东西,追番...
fight !!!
-----------------------------------
11.18
cf 734 e E - Anton and Tree
给一颗 n 个节点 ,每个节点 是 黑色或者白色,每次操作可以将 一整个连通块的颜色变成相反的颜色
求将这整棵树 变成同色至少需要多少次操作
最开始 错误的做法 是:
分别 去 dfs 了一下 白色,黑色的连通块 的个数,然后 取了个最小值
但是这样不对,因为在消除变色的过程中,分支 也会跟着变化
把每个相同颜色的连通块 缩点,缩完点之后,就变成黑白相间的树了
操作次数 是(直径+1)/2
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 4e5+5; 9 int n,bcc_cnt; 10 vector<int> g[maxn]; 11 int col[maxn],vis[maxn],dep[maxn]; 12 vector<int> G[maxn]; 13 14 void dfs1(int u,int fa){ 15 vis[u] = bcc_cnt; 16 for(int i = 0;i < g[u].size();i++){ 17 int v = g[u][i]; 18 if(col[v] != 0 || vis[v]) continue; 19 dfs1(v,u); 20 } 21 } 22 23 void dfs2(int u,int fa){ 24 vis[u] = bcc_cnt; 25 for(int i = 0;i < g[u].size();i++){ 26 int v = g[u][i]; 27 if(col[v] != 1 || vis[v]) continue; 28 dfs2(v,u); 29 } 30 } 31 32 void Dfs(int u,int d){ 33 dep[u] = d; 34 for(int i = 0;i < G[u].size();i++){ 35 int v = G[u][i]; 36 if(dep[v] != -1) continue; 37 Dfs(v,d+1); 38 } 39 } 40 41 42 43 void solve(){ 44 memset(vis,0,sizeof(vis)); 45 bcc_cnt = n; 46 for(int i = 1;i <= n;i++){ 47 if(col[i] == 0 && !vis[i]){ 48 ++bcc_cnt; 49 dfs1(i,-1); 50 } 51 } 52 for(int i = 1;i <= n;i++){ 53 if(col[i] == 1 && !vis[i]){ 54 ++bcc_cnt; 55 dfs2(i,-1); 56 } 57 } 58 //for(int i = 1;i <= n;i++) printf("vis[%d] = %d\n",i,vis[i]); 59 for(int i = 1;i < maxn;i++) G[i].clear(); 60 for(int i = 1;i <= n;i++){ 61 for(int j = 0;j < g[i].size();j++){ 62 int u = vis[i]; 63 int v = vis[g[i][j]]; 64 if(u != v){ 65 G[u].push_back(v); 66 G[v].push_back(u); 67 } 68 } 69 } 70 71 memset(dep,-1,sizeof(dep)); 72 int mn = 0,st,ed; 73 Dfs(bcc_cnt,0); 74 for(int i = n+1;i <= bcc_cnt;i++){ 75 // printf("dep[%d] = %d\n",i,dep[i]); 76 if(dep[i] >= mn){ 77 mn = dep[i]; 78 st = i; 79 } 80 } 81 82 memset(dep,-1,sizeof(dep)); 83 Dfs(st,0); 84 //printf("st = %d\n",st); 85 int ans = 0; 86 for(int i =n+1;i <= bcc_cnt;i++) { 87 //printf("--- dep[%d] = %d\n",i,dep[i]); 88 ans = max(ans,dep[i]); 89 } 90 printf("%d\n",(ans+1)/2); 91 } 92 93 int main(){ 94 while(scanf("%d",&n) != EOF){ 95 memset(col,0,sizeof(col)); 96 for(int i = 1;i <= n;i++) g[i].clear(); 97 for(int i = 1;i <= n;i++) scanf("%d",&col[i]); 98 int u,v; 99 for(int i = 1;i < n;i++){ 100 scanf("%d %d",&u,&v); 101 g[u].push_back(v); 102 g[v].push_back(u); 103 } 104 solve(); 105 } 106 return 0; 107 }