# bzoj 1016 最小生成树计数

  1 #include <cstdio>
2 #include <cstring>
3 #include <map>
4 #include <vector>
5 #include <algorithm>
6 #define abs(a) ((a)<0?-(a):(a))
7 #define M 31011
8 #define maxn 110
9 using namespace std;
10
11 struct Edge {
12     int u, v, w;
13     Edge( int u, int v, int w ) : u(u), v(v), w(w) {}
14     bool operator<( const Edge & b ) const {
15         return w<b.w;
16     }
17 };
18
19 typedef int Matrix[maxn][maxn];
20
21 int n, m;
22 vector<Edge> edge;
23
24 int fa[maxn];
25
26 void init() {
27     for( int i=1; i<=n; i++ ) fa[i]=i;
28 }
29 int find( int a ) {
30     return fa[a]==a ? a : fa[a]=find(fa[a]);
31 }
32 void unon( int a, int b ) {
33     a = find(a);
34     b = find(b);
35     fa[a] = b;
36 }
37
38 int det( Matrix a, int n ) {
39     for( int i=0; i<n; i++ ) {
40         int r = i;
41         for( int j=i+1; j<n; j++ )
42             if( abs(a[j][i])>abs(a[r][i]) ) r=j;
43         if( r!=i )
44             for( int k=i; k<n; k++ )
45                 swap( a[i][k], a[r][k] );
46         if( a[i][i]==0 ) return 0;
47         for( int j=i+1; j<n; j++ ) {
48             while( a[j][i] ) {
49                 int d = a[i][i] / a[j][i];
50                 for( int k=i; k<n; k++ ) {
51                     a[i][k] = (a[i][k]-a[j][k]*d%M)%M;
52                     swap( a[i][k], a[j][k] );
53                 }
54             }
55         }
56     }
57     int rt = 1;
58     for( int i=0; i<n; i++ )
59         rt = (rt*a[i][i])%M;
60     return abs(rt);
61 }
62
63 int subfa[30], cnt;
64 Matrix a;
65 int sfind( int a ) {
66     return a==subfa[a] ? a : subfa[a]=sfind(subfa[a]);
67 }
68 void sunon( int a, int b ) {
69     a = sfind(a);
70     b = sfind(b);
71     if( b<a ) subfa[a] = b;
72     else subfa[b] = a;
73 }
74 int pm( map<int,int> &mp, int i ) { return mp[i]; }
75 int calc( const vector<Edge> & e ) {
76     vector<int> cc[30];
77     map<int,int> mp;
78     cnt = 0;
79     for( int i=0; i<e.size(); i++ ) {
80         int u = e[i].u, v = e[i].v;
81         if( !mp.count(find(u)) ) mp[find(u)]=cnt++;
82         if( !mp.count(find(v)) ) mp[find(v)]=cnt++;
83     }
84     for( int i=0; i<mp.size(); i++ ) subfa[i] = i;
85     for( int i=0; i<e.size(); i++ ) {
86         int u = e[i].u, v = e[i].v;
87         sunon( mp[find(u)], mp[find(v)] );
88     }
89     int rt = 1;
90     for( int i=0; i<cnt; i++ )
91         cc[sfind(i)].push_back(i);
92     for( int c=0; cc[c].size(); c++ ) {
93         if( cc[c].size()==1 ) continue;
94         map<int,int> np;
95         for( int t=0; t<cc[c].size(); t++ )
96             np[cc[c][t]] = t;
97         memset( a, 0, sizeof(a) );
98         for( int i=0; i<e.size(); i++ ) {
99             int u = np[mp[find(e[i].u)]];
100             int v = np[mp[find(e[i].v)]];
101             a[u][u]++;
102             a[v][v]++;
103             a[u][v]--;
104             a[v][u]--;
105         }
106         rt = (rt*det(a,cc[c].size()-1))%M;
107     }
108     return rt;
109 }
110 void work() {
111     sort( edge.begin(), edge.end() );
112     init();
113     vector<Edge> e;
114     int ans = 1;
115     for( int i=0; i<edge.size(); ) {
116         do
117             e.push_back( edge[i++] );
118         while( i<edge.size() && edge[i].w==edge[i-1].w );
119         ans = (ans*calc(e))%M;
120         while( !e.empty() ) {
121             unon( e.back().u, e.back().v );
122             e.pop_back();
123         }
124     }
125     for( int i=2; i<=n; i++ )
126         if( find(i)!=find(i-1) ) {
127             ans=0;
128             break;
129         }
130     printf( "%d\n", ans );
131 }
132
133 int main() {
134     scanf( "%d%d", &n, &m );
135     for( int i=0,u,v,w; i<m; i++ ) {
136         scanf( "%d%d%d", &u, &v, &w );
137         edge.push_back( Edge(u,v,w) );
138     }
139     work();
140 }
View Code

posted @ 2015-02-20 16:02  idy002  阅读(...)  评论(... 编辑 收藏