码迷,mamicode.com
首页 > 其他好文 > 详细

最小生成树计数

时间:2014-08-29 14:27:18      阅读:261      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   ar   for   art   

Minimum Spanning Tree http://acm.hdu.edu.cn/showproblem.php?pid=4408

模板题

bubuko.com,布布扣
  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 }
View Code

 

1016: [JSOI2008]最小生成树计数 http://www.lydsy.com/JudgeOnline/problem.php?id=1016

一样

bubuko.com,布布扣
  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 }
View Code

 

 

end

最小生成树计数

标签:style   blog   http   color   os   io   ar   for   art   

原文地址:http://www.cnblogs.com/gaolzzxin/p/3944788.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!