Minimum Spanning Tree http://acm.hdu.edu.cn/showproblem.php?pid=4408
模板题
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 typedef __int64 LL; 8 class MinST_count { ///最小生成树计数 9 typedef int typec;///边权的类型 10 static const int ME=1024;///边的个数 11 static const int MV=128;///点的个数 12 struct E { 13 int u,v; 14 typec w; 15 friend bool operator <(E a,E b) { 16 return a.w<b.w; 17 } 18 } e[ME]; 19 LL mod,ans,mat[MV][MV]; 20 int n,le,fa[MV],ka[MV],gk[MV][MV]; 21 bool vis[MV]; 22 vector<int> gra[MV]; 23 int getroot(int a,int b[]) { 24 return a==b[a]?a:b[a]=getroot(b[a],b); 25 } 26 LL det(LL a[][MV],int n) { ///生成树计数 27 for(int i=0; i<n; i++) 28 for(int j=0; j<n; j++) 29 a[i][j]%=mod; 30 LL ret=1; 31 for(int i=1; i<n; i++) { 32 for(int j=i+1; j<n; j++) { 33 while(a[j][i]) { 34 LL t=a[i][i]/a[j][i]; 35 for(int k=i; k<n; k++) 36 a[i][k]=(a[i][k]-a[j][k]*t)%mod; 37 for(int k=i; k<n; k++) 38 swap(a[i][k],a[j][k]); 39 ret=-ret; 40 } 41 } 42 if(!a[i][i]) return 0; 43 ret=ret*a[i][i]%mod; 44 } 45 return (ret+mod)%mod; 46 } 47 public: 48 void init(int tn,int tmod) { ///传入点的个数,%tmod,点下标1开始 49 n=tn; 50 mod=tmod; 51 le=0; 52 mt(fa,0); 53 mt(ka,0); 54 mt(vis,0); 55 mt(gk,0); 56 mt(mat,0); 57 } 58 void add(int u,int v,typec w) { 59 e[le].u=u; 60 e[le].v=v; 61 e[le].w=w; 62 le++; 63 } 64 LL solve() {///返回生成树个数%mod 65 sort(e,e+le); 66 for(int i=1; i<=n; i++){ 67 fa[i]=i; 68 vis[i]=false; 69 gra[i].clear(); 70 } 71 typec pre=-1; 72 ans=1; 73 for(int h=0; h<=le; h++) { 74 if(e[h].w!=pre||h==le) { ///一组边加完 75 for(int i=1; i<=n; i++) { 76 if(vis[i]) { 77 int u=getroot(i,ka); 78 gra[u].push_back(i); 79 vis[i]=false; 80 } 81 } 82 for(int i=1; i<=n; i++) { ///枚举每个联通分量 83 if(gra[i].size()>1) { 84 mt(mat,0); 85 int len=gra[i].size(); 86 for(int a=0; a<len; a++) { ///构建矩阵 87 for(int b=a+1; b<len; b++) { 88 LL la=gra[i][a],lb=gra[i][b]; 89 mat[a][b]=(mat[b][a]-=gk[la][lb]); 90 mat[a][a]+=gk[la][lb]; 91 mat[b][b]+=gk[la][lb]; 92 } 93 } 94 LL ret=(LL)det(mat,len); 95 ans=(ans*ret)%mod; 96 for(int a=0; a<len; a++) 97 fa[gra[i][a]]=i; 98 } 99 } 100 for(int i=1; i<=n; i++) { 101 ka[i]=fa[i]=getroot(i,fa); 102 gra[i].clear(); 103 } 104 if(h==le)break; 105 pre=e[h].w; 106 } 107 int a=e[h].u; 108 int b=e[h].v; 109 int pa=getroot(a,fa); 110 int pb=getroot(b,fa); 111 if(pa==pb)continue; 112 vis[pa]=vis[pb]=true; 113 ka[getroot(pa,ka)]=getroot(pb,ka); 114 gk[pa][pb]++; 115 gk[pb][pa]++; 116 } 117 for(int i=2; i<=n&&ans; i++) 118 if(ka[i]!=ka[i-1]) 119 ans=0; 120 ans=(ans+mod)%mod; 121 return ans; 122 } 123 }gx; 124 int main() { 125 int n,m,p; 126 while(~scanf("%d%d%d",&n,&m,&p),n|m|p) { 127 gx.init(n,p); 128 while(m--) { 129 int u,v,w; 130 scanf("%d%d%d",&u,&v,&w); 131 gx.add(u,v,w); 132 } 133 printf("%I64d\n",gx.solve()); 134 } 135 return 0; 136 }
1016: [JSOI2008]最小生成树计数 http://www.lydsy.com/JudgeOnline/problem.php?id=1016
一样
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 typedef long long LL; 8 class MinST_count { ///最小生成树计数 9 typedef int typec;///边权的类型 10 static const int ME=1024;///边的个数 11 static const int MV=128;///点的个数 12 struct E { 13 int u,v; 14 typec w; 15 friend bool operator <(E a,E b) { 16 return a.w<b.w; 17 } 18 } e[ME]; 19 LL mod,ans,mat[MV][MV]; 20 int n,le,fa[MV],ka[MV],gk[MV][MV]; 21 bool vis[MV]; 22 vector<int> gra[MV]; 23 int getroot(int a,int b[]) { 24 return a==b[a]?a:b[a]=getroot(b[a],b); 25 } 26 LL det(LL a[][MV],int n) { ///生成树计数 27 for(int i=0; i<n; i++) 28 for(int j=0; j<n; j++) 29 a[i][j]%=mod; 30 LL ret=1; 31 for(int i=1; i<n; i++) { 32 for(int j=i+1; j<n; j++) { 33 while(a[j][i]) { 34 LL t=a[i][i]/a[j][i]; 35 for(int k=i; k<n; k++) 36 a[i][k]=(a[i][k]-a[j][k]*t)%mod; 37 for(int k=i; k<n; k++) 38 swap(a[i][k],a[j][k]); 39 ret=-ret; 40 } 41 } 42 if(!a[i][i]) return 0; 43 ret=ret*a[i][i]%mod; 44 } 45 return (ret+mod)%mod; 46 } 47 public: 48 void init(int tn,int tmod) { ///传入点的个数,%tmod,点下标1开始 49 n=tn; 50 mod=tmod; 51 le=0; 52 mt(fa,0); 53 mt(ka,0); 54 mt(vis,0); 55 mt(gk,0); 56 mt(mat,0); 57 } 58 void add(int u,int v,typec w) { 59 e[le].u=u; 60 e[le].v=v; 61 e[le].w=w; 62 le++; 63 } 64 LL solve() {///返回生成树个数%mod 65 sort(e,e+le); 66 for(int i=1; i<=n; i++){ 67 fa[i]=i; 68 vis[i]=false; 69 gra[i].clear(); 70 } 71 typec pre=-1; 72 ans=1; 73 for(int h=0; h<=le; h++) { 74 if(e[h].w!=pre||h==le) { ///一组边加完 75 for(int i=1; i<=n; i++) { 76 if(vis[i]) { 77 int u=getroot(i,ka); 78 gra[u].push_back(i); 79 vis[i]=false; 80 } 81 } 82 for(int i=1; i<=n; i++) { ///枚举每个联通分量 83 if(gra[i].size()>1) { 84 mt(mat,0); 85 int len=gra[i].size(); 86 for(int a=0; a<len; a++) { ///构建矩阵 87 for(int b=a+1; b<len; b++) { 88 LL la=gra[i][a],lb=gra[i][b]; 89 mat[a][b]=(mat[b][a]-=gk[la][lb]); 90 mat[a][a]+=gk[la][lb]; 91 mat[b][b]+=gk[la][lb]; 92 } 93 } 94 LL ret=(LL)det(mat,len); 95 ans=(ans*ret)%mod; 96 for(int a=0; a<len; a++) 97 fa[gra[i][a]]=i; 98 } 99 } 100 for(int i=1; i<=n; i++) { 101 ka[i]=fa[i]=getroot(i,fa); 102 gra[i].clear(); 103 } 104 if(h==le)break; 105 pre=e[h].w; 106 } 107 int a=e[h].u; 108 int b=e[h].v; 109 int pa=getroot(a,fa); 110 int pb=getroot(b,fa); 111 if(pa==pb)continue; 112 vis[pa]=vis[pb]=true; 113 ka[getroot(pa,ka)]=getroot(pb,ka); 114 gk[pa][pb]++; 115 gk[pb][pa]++; 116 } 117 for(int i=2; i<=n&&ans; i++) 118 if(ka[i]!=ka[i-1]) 119 ans=0; 120 ans=(ans+mod)%mod; 121 return ans; 122 } 123 }gx; 124 int main() { 125 int n,m,p; 126 while(~scanf("%d%d",&n,&m)) { 127 gx.init(n,31011); 128 while(m--) { 129 int u,v,w; 130 scanf("%d%d%d",&u,&v,&w); 131 gx.add(u,v,w); 132 } 133 printf("%lld\n",gx.solve()); 134 } 135 return 0; 136 }
end
时间: 2024-09-29 19:33:21