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\n",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\n",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\n",ans);
164 }
165 return 0;
166 }
end
来源:https://www.cnblogs.com/gaolzzxin/p/3944788.html
