BZOJ 1016 [JSOI2008]最小生成树计数 dfs
题解:
最小生成树的两个性质:
1、边权相等的边的个数一定。
2、做完边权为w的所有边时,图的连通性相同。
然后就暴力dfs吧~
View Code
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdlib> 5 #include <cstring> 6 7 #define N 2000 8 #define M 30000 9 #define mod 31011 10 11 using namespace std; 12 13 struct KRU 14 { 15 int a,b,d; 16 }kru[M]; 17 18 int n,m,fa[N],f2[N],st[M],sum[M],cnt,ans=1,tans; 19 bool vis[N]; 20 21 22 inline bool cmp(const KRU &a,const KRU &b) 23 { 24 return a.d<b.d; 25 } 26 27 void read() 28 { 29 scanf("%d%d",&n,&m); 30 for(int i=1;i<=m;i++) scanf("%d%d%d",&kru[i].a,&kru[i].b,&kru[i].d); 31 sort(kru+1,kru+1+m,cmp); 32 } 33 34 int findfa(int x) 35 { 36 if(x!=fa[x]) fa[x]=findfa(fa[x]); 37 return fa[x]; 38 } 39 40 int findpa(int x) 41 { 42 if(x!=f2[x]) return findpa(f2[x]); 43 return x; 44 } 45 46 void dfs(int l,int r,int num) 47 { 48 if(num==0) {tans++;return;} 49 if(l>r) return; 50 int fx=findpa(kru[l].a),fy=findpa(kru[l].b); 51 if(vis[kru[l].a]&&vis[kru[l].b]&&fx!=fy) 52 { 53 f2[fx]=fy; 54 dfs(l+1,r,num-1); 55 f2[fx]=fx; 56 } 57 dfs(l+1,r,num); 58 } 59 60 void work(int x) 61 { 62 tans=0; 63 dfs(st[x],st[x+1]-1,sum[x]); 64 ans=(ans*tans)%mod; 65 } 66 67 void kruskal() 68 { 69 memset(vis,0,sizeof vis); 70 for(int i=1;i<=n;i++) fa[i]=f2[i]=i; 71 int num=1,i; 72 cnt=0; 73 for(i=1;i<=m;i++) 74 { 75 if(i==1||kru[i].d!=kru[i-1].d) 76 { 77 st[++cnt]=i; sum[cnt]=0; 78 if(i!=1) work(cnt-1); 79 for(int j=1;j<=n;j++) f2[j]=fa[j]; 80 } 81 if(findfa(kru[i].a)!=findfa(kru[i].b)) 82 { 83 num++; sum[cnt]++; 84 fa[findfa(kru[i].a)]=findfa(kru[i].b); 85 vis[kru[i].a]=vis[kru[i].b]=true; 86 } 87 if(num==n) break; 88 } 89 kru[m+1].d=-1; 90 for(int j=i+1;j<=m+1;j++) 91 if(kru[j-1].d!=kru[j].d) 92 { 93 st[cnt+1]=j; 94 break; 95 } 96 work(cnt); 97 if(num==n) printf("%d\n",ans); 98 else printf("0\n"); 99 } 100 101 int main() 102 { 103 read(),kruskal(); 104 return 0; 105 }
没有人能阻止我前进的步伐,除了我自己!