Minimum Spanning Tree http://acm.hdu.edu.cn/showproblem.php?pid=4408
模板题
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<algorithm> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 typedef __int64 LL; 9 class MinST_count { ///最小生成树计数o(~=MV^3)+o(MElogME) 10 typedef int typec;///边权的类型 11 typedef LL typer;///返回值类型 12 static const int ME=1024;///边的个数 13 static const int MV=128;///点的个数 14 struct E { 15 int u,v; 16 typec w; 17 friend bool operator <(E a,E b) { 18 return a.w<b.w; 19 } 20 } e[ME]; 21 typer mod,ans,mat[MV][MV]; 22 int n,le,fa[MV],ka[MV],gk[MV][MV]; 23 bool vis[MV]; 24 vector<int> gra[MV]; 25 int getroot(int a,int b[]) { 26 return a==b[a]?a:b[a]=getroot(b[a],b); 27 } 28 typer det(typer a[][MV],int n) { ///生成树计数 29 for(int i=0; i<n; i++) 30 for(int j=0; j<n; j++) 31 a[i][j]%=mod; 32 typer ret=1; 33 for(int i=1; i<n; i++) { 34 for(int j=i+1; j<n; j++) { 35 while(a[j][i]) { 36 typer t=a[i][i]/a[j][i]; 37 for(int k=i; k<n; k++) 38 a[i][k]=(a[i][k]-a[j][k]*t)%mod; 39 for(int k=i; k<n; k++) 40 swap(a[i][k],a[j][k]); 41 ret=-ret; 42 } 43 } 44 if(!a[i][i]) return 0; 45 ret=ret*a[i][i]%mod; 46 } 47 return (ret+mod)%mod; 48 } 49 public: 50 void init(int tn,int tmod) { ///传入点的个数,%tmod,点下标1开始 51 n=tn; 52 mod=tmod; 53 le=0; 54 mt(fa,0); 55 mt(ka,0); 56 mt(vis,0); 57 mt(gk,0); 58 mt(mat,0); 59 } 60 void add(int u,int v,typec w) { 61 e[le].u=u; 62 e[le].v=v; 63 e[le].w=w; 64 le++; 65 } 66 typer solve() {///返回生成树个数%mod 67 sort(e,e+le); 68 for(int i=1; i<=n; i++) { 69 fa[i]=i; 70 vis[i]=false; 71 gra[i].clear(); 72 } 73 typec pre=-1; 74 ans=1; 75 for(int h=0; h<=le; h++) { 76 if(e[h].w!=pre||h==le) { ///一组边加完 77 for(int i=1; i<=n; i++) { 78 if(vis[i]) { 79 int u=getroot(i,ka); 80 gra[u].push_back(i); 81 vis[i]=false; 82 } 83 } 84 for(int i=1; i<=n; i++) { ///枚举每个联通分量 85 if(gra[i].size()>1) { 86 mt(mat,0); 87 int len=gra[i].size(); 88 for(int a=0; a<len; a++) { ///构建矩阵 89 for(int b=a+1; b<len; b++) { 90 typer la=gra[i][a],lb=gra[i][b]; 91 mat[a][b]=(mat[b][a]-=gk[la][lb]); 92 mat[a][a]+=gk[la][lb]; 93 mat[b][b]+=gk[la][lb]; 94 } 95 } 96 typer ret=(typer)det(mat,len); 97 ans=(ans*ret)%mod; 98 for(int a=0; a<len; a++) 99 fa[gra[i][a]]=i; 100 } 101 } 102 for(int i=1; i<=n; i++) { 103 ka[i]=fa[i]=getroot(i,fa); 104 gra[i].clear(); 105 } 106 if(h==le)break; 107 pre=e[h].w; 108 } 109 int a=e[h].u; 110 int b=e[h].v; 111 int pa=getroot(a,fa); 112 int pb=getroot(b,fa); 113 if(pa==pb)continue; 114 vis[pa]=vis[pb]=true; 115 ka[getroot(pa,ka)]=getroot(pb,ka); 116 gk[pa][pb]++; 117 gk[pb][pa]++; 118 } 119 for(int i=2; i<=n&&ans; i++) 120 if(ka[i]!=ka[i-1]) 121 ans=0; 122 ans=(ans+mod)%mod; 123 return ans; 124 } 125 } gx; 126 int main(){ 127 int n,m,p,u,v,w; 128 while(~scanf("%d%d%d",&n,&m,&p),n|m|p){ 129 gx.init(n,p); 130 while(m--){ 131 scanf("%d%d%d",&u,&v,&w); 132 gx.add(u,v,w); 133 } 134 printf("%I64d ",gx.solve()); 135 } 136 return 0; 137 }
1016: [JSOI2008]最小生成树计数 http://www.lydsy.com/JudgeOnline/problem.php?id=1016
一样
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<stack> 5 #include<algorithm> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 class MinST_count { ///最小生成树计数o(~=MV^3)+o(MElogME) 9 typedef int typec;///边权的类型 10 typedef int typer;///返回值类型 11 static const int ME=1024;///边的个数 12 static const int MV=128;///点的个数 13 struct E { 14 int u,v; 15 typec w; 16 friend bool operator <(E a,E b) { 17 return a.w<b.w; 18 } 19 } e[ME]; 20 typer mod,ans,mat[MV][MV]; 21 int n,le,fa[MV],ka[MV],gk[MV][MV]; 22 bool vis[MV]; 23 vector<int> gra[MV]; 24 int getroot(int a,int b[]) { 25 return a==b[a]?a:b[a]=getroot(b[a],b); 26 } 27 typer det(typer a[][MV],int n) { ///生成树计数 28 for(int i=0; i<n; i++) 29 for(int j=0; j<n; j++) 30 a[i][j]%=mod; 31 typer ret=1; 32 for(int i=1; i<n; i++) { 33 for(int j=i+1; j<n; j++) { 34 while(a[j][i]) { 35 typer t=a[i][i]/a[j][i]; 36 for(int k=i; k<n; k++) 37 a[i][k]=(a[i][k]-a[j][k]*t)%mod; 38 for(int k=i; k<n; k++) 39 swap(a[i][k],a[j][k]); 40 ret=-ret; 41 } 42 } 43 if(!a[i][i]) return 0; 44 ret=ret*a[i][i]%mod; 45 } 46 return (ret+mod)%mod; 47 } 48 public: 49 void init(int tn,int tmod) { ///传入点的个数,%tmod,点下标1开始 50 n=tn; 51 mod=tmod; 52 le=0; 53 mt(fa,0); 54 mt(ka,0); 55 mt(vis,0); 56 mt(gk,0); 57 mt(mat,0); 58 } 59 void add(int u,int v,typec w) { 60 e[le].u=u; 61 e[le].v=v; 62 e[le].w=w; 63 le++; 64 } 65 typer solve() {///返回生成树个数%mod 66 sort(e,e+le); 67 for(int i=1; i<=n; i++) { 68 fa[i]=i; 69 vis[i]=false; 70 gra[i].clear(); 71 } 72 typec pre=-1; 73 ans=1; 74 for(int h=0; h<=le; h++) { 75 if(e[h].w!=pre||h==le) { ///一组边加完 76 for(int i=1; i<=n; i++) { 77 if(vis[i]) { 78 int u=getroot(i,ka); 79 gra[u].push_back(i); 80 vis[i]=false; 81 } 82 } 83 for(int i=1; i<=n; i++) { ///枚举每个联通分量 84 if(gra[i].size()>1) { 85 mt(mat,0); 86 int len=gra[i].size(); 87 for(int a=0; a<len; a++) { ///构建矩阵 88 for(int b=a+1; b<len; b++) { 89 typer la=gra[i][a],lb=gra[i][b]; 90 mat[a][b]=(mat[b][a]-=gk[la][lb]); 91 mat[a][a]+=gk[la][lb]; 92 mat[b][b]+=gk[la][lb]; 93 } 94 } 95 typer ret=(typer)det(mat,len); 96 ans=(ans*ret)%mod; 97 for(int a=0; a<len; a++) 98 fa[gra[i][a]]=i; 99 } 100 } 101 for(int i=1; i<=n; i++) { 102 ka[i]=fa[i]=getroot(i,fa); 103 gra[i].clear(); 104 } 105 if(h==le)break; 106 pre=e[h].w; 107 } 108 int a=e[h].u; 109 int b=e[h].v; 110 int pa=getroot(a,fa); 111 int pb=getroot(b,fa); 112 if(pa==pb)continue; 113 vis[pa]=vis[pb]=true; 114 ka[getroot(pa,ka)]=getroot(pb,ka); 115 gk[pa][pb]++; 116 gk[pb][pa]++; 117 } 118 for(int i=2; i<=n&&ans; i++) 119 if(ka[i]!=ka[i-1]) 120 ans=0; 121 ans=(ans+mod)%mod; 122 return ans; 123 } 124 } gx; 125 int main(){ 126 int n,m,u,v,w; 127 while(~scanf("%d%d",&n,&m)){ 128 gx.init(n,31011); 129 while(m--){ 130 scanf("%d%d%d",&u,&v,&w); 131 gx.add(u,v,w); 132 } 133 printf("%d ",gx.solve()); 134 } 135 return 0; 136 }
Lightning http://acm.hdu.edu.cn/showproblem.php?pid=4305
首先是根据两点的距离不大于R,而且中间没有点建立一个图。之后就是求生成树计数了。需要强调的是计算几何部分用double来做超时,计数部分用long long也超时,全用int才能过。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #include<vector> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 #define zero(x) (((x)>0?(x):-(x))<eps) 8 using namespace std; 9 const double eps=1e-8; 10 struct point { 11 int x,y; 12 } p[310]; 13 int Distance2(point p1,point p2) { 14 return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y); 15 } 16 int xmult(point p1,point p2,point p0) { 17 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 18 } 19 int dot_online_in(point p,point l1,point l2) { 20 return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps; 21 } 22 int n,R; 23 bool check(int k1,int k2) { ///判断两点的距离小于等于R,而且中间没有点阻隔 24 if(Distance2(p[k1],p[k2]) > R*R)return false; 25 for(int i = 0; i < n; i++) 26 if(i!=k1 && i!=k2) 27 if(dot_online_in(p[i],p[k1],p[k2])) 28 return false; 29 return true; 30 } 31 class MinST_count { ///最小生成树计数o(~=MV^3)+o(MElogME) 32 typedef int typec;///边权的类型 33 typedef int typer;///返回值类型 34 static const int ME=90010;///边的个数 35 static const int MV=310;///点的个数 36 struct E { 37 int u,v; 38 typec w; 39 friend bool operator <(E a,E b) { 40 return a.w<b.w; 41 } 42 } e[ME]; 43 typer mod,ans,mat[MV][MV]; 44 int n,le,fa[MV],ka[MV],gk[MV][MV]; 45 bool vis[MV]; 46 vector<int> gra[MV]; 47 int getroot(int a,int b[]) { 48 return a==b[a]?a:b[a]=getroot(b[a],b); 49 } 50 typer det(typer a[][MV],int n) { ///生成树计数 51 for(int i=0; i<n; i++) 52 for(int j=0; j<n; j++) 53 a[i][j]%=mod; 54 typer ret=1; 55 for(int i=1; i<n; i++) { 56 for(int j=i+1; j<n; j++) { 57 while(a[j][i]) { 58 typer t=a[i][i]/a[j][i]; 59 for(int k=i; k<n; k++) 60 a[i][k]=(a[i][k]-a[j][k]*t)%mod; 61 for(int k=i; k<n; k++) 62 swap(a[i][k],a[j][k]); 63 ret=-ret; 64 } 65 } 66 if(!a[i][i]) return 0; 67 ret=ret*a[i][i]%mod; 68 } 69 return (ret+mod)%mod; 70 } 71 public: 72 void init(int tn,int tmod) { ///传入点的个数,%tmod,点下标1开始 73 n=tn; 74 mod=tmod; 75 le=0; 76 mt(fa,0); 77 mt(ka,0); 78 mt(vis,0); 79 mt(gk,0); 80 mt(mat,0); 81 } 82 void add(int u,int v,typec w) { 83 e[le].u=u; 84 e[le].v=v; 85 e[le].w=w; 86 le++; 87 } 88 typer solve() {///返回生成树个数%mod 89 sort(e,e+le); 90 for(int i=1; i<=n; i++) { 91 fa[i]=i; 92 vis[i]=false; 93 gra[i].clear(); 94 } 95 typec pre=-1; 96 ans=1; 97 for(int h=0; h<=le; h++) { 98 if(e[h].w!=pre||h==le) { ///一组边加完 99 for(int i=1; i<=n; i++) { 100 if(vis[i]) { 101 int u=getroot(i,ka); 102 gra[u].push_back(i); 103 vis[i]=false; 104 } 105 } 106 for(int i=1; i<=n; i++) { ///枚举每个联通分量 107 if(gra[i].size()>1) { 108 mt(mat,0); 109 int len=gra[i].size(); 110 for(int a=0; a<len; a++) { ///构建矩阵 111 for(int b=a+1; b<len; b++) { 112 typer la=gra[i][a],lb=gra[i][b]; 113 mat[a][b]=(mat[b][a]-=gk[la][lb]); 114 mat[a][a]+=gk[la][lb]; 115 mat[b][b]+=gk[la][lb]; 116 } 117 } 118 typer ret=(typer)det(mat,len); 119 ans=(ans*ret)%mod; 120 for(int a=0; a<len; a++) 121 fa[gra[i][a]]=i; 122 } 123 } 124 for(int i=1; i<=n; i++) { 125 ka[i]=fa[i]=getroot(i,fa); 126 gra[i].clear(); 127 } 128 if(h==le)break; 129 pre=e[h].w; 130 } 131 int a=e[h].u; 132 int b=e[h].v; 133 int pa=getroot(a,fa); 134 int pb=getroot(b,fa); 135 if(pa==pb)continue; 136 vis[pa]=vis[pb]=true; 137 ka[getroot(pa,ka)]=getroot(pb,ka); 138 gk[pa][pb]++; 139 gk[pb][pa]++; 140 } 141 for(int i=2; i<=n&&ans; i++) 142 if(ka[i]!=ka[i-1]) 143 ans=0; 144 ans=(ans+mod)%mod; 145 return ans; 146 } 147 } gx; 148 int main() { 149 int T; 150 scanf("%d",&T); 151 while(T--) { 152 scanf("%d%d",&n,&R); 153 for(int i = 0; i < n; i++){ 154 scanf("%d%d",&p[i].x,&p[i].y); 155 } 156 gx.init(n,10007); 157 for(int i = 0; i < n; i++) 158 for(int j = i+1; j <n; j++) 159 if(check(i,j)) 160 gx.add(i+1,j+1,1); 161 int ans=gx.solve(); 162 if(!ans) ans=-1; 163 printf("%d ",ans); 164 } 165 return 0; 166 }
end