BZOJ 1016: [JSOI2008]最小產生樹計數

來源:互聯網
上載者:User

標籤:scan   set   pll   http   img   inf   font   php   注意   

http://www.lydsy.com/JudgeOnline/problem.php?id=1016

題意:

 

思路:

一個無向圖所有的最小產生樹中某種權值的邊的數目均相同。

引用一篇大牛的證明:

我們證明以下定理:一個無向圖所有的最小產生樹中某種權值的邊的數目均相同。

開始時,每個點單獨構成一個集合。

首先只考慮權值最小的邊,將它們全部添加進圖中,並去掉環,由於是全部嘗試添加,那麼只要是用這種權值的邊能夠連通的點,最終就一定能在一個集合中。

那麼不管添加的是哪些邊,最終形成的集合數都是一定的,且集合的劃分情況一定相同。那麼真正添加的邊數也是相同的。因為每添加一條邊集合的數目便減少1.

那麼權值第二小的邊呢?我們將之間得到的集合每個集合都縮為一個點,那麼權值第二小的邊就變成了當前權值最小的邊,也有上述的結論。

因此每個階段,添加的邊數都是相同的。我們以權值劃分階段,那麼也就意味著某種權值的邊的數目是完全相同的。

 

所以先用克魯斯卡爾演算法計算一遍最小產生樹,統計每一權值的邊組需要加幾條邊,最後暴搜,乘法原理相乘即可。注意,要判斷無法連通的情況。

 

  1 #include<iostream>  2 #include<algorithm>  3 #include<cstring>  4 #include<cstdio>  5 #include<sstream>  6 #include<vector>  7 #include<stack>  8 #include<queue>  9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,ll> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn=10000+5; 17 const int mod=31011; 18  19 struct node 20 { 21     int u,v,w; 22 }e[10*maxn]; 23  24 struct node2 25 { 26     int l,r; 27     int c; 28 }a[maxn]; 29  30 int n, m; 31 int sum; 32 int cnt,tot; 33 int p[maxn]; 34  35 bool cmp(node a, node b) 36 { 37     return a.w<b.w; 38 } 39  40 int find(int x) 41 { 42     return x==p[x]?x:find(p[x]); 43 } 44  45 void dfs(int cur, int num ,int pos) 46 { 47     if(pos>a[cur].r) 48     { 49         if(num==a[cur].c) sum++; 50         return; 51     } 52     int x=find(e[pos].u); 53     int y=find(e[pos].v); 54     if(x!=y) 55     { 56         p[x]=y; 57         dfs(cur,num+1,pos+1); 58         p[x]=x; 59     } 60     dfs(cur,num,pos+1); 61 } 62  63 int main() 64 { 65     //freopen("in.txt","r",stdin); 66     while(~scanf("%d%d",&n,&m)) 67     { 68         for(int i=1;i<=n;i++) p[i]=i; 69         for(int i=1;i<=m;i++) 70             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); 71  72         sort(e+1,e+m+1,cmp); 73         cnt=0; tot=0; 74         for(int i=1;i<=m;i++) 75         { 76             if(e[i].w!=e[i-1].w) 77             { 78                 a[++cnt].l=i; 79                 a[cnt-1].r=i-1; 80                 a[cnt].c=0; 81             } 82             int x=find(e[i].u); 83             int y=find(e[i].v); 84             if(x!=y) 85             { 86                 p[x]=y; 87                 a[cnt].c++; 88                 tot++; 89             } 90         } 91         a[cnt].r=m; 92          93         if(tot!=n-1)  //連不起來的情況 94         { 95             printf("0\n"); 96             continue; 97         } 98          99 100         for(int i=1;i<=n;i++)   p[i]=i;101         int ans=1;102         for(int i=1;i<=cnt;i++)103         {104             sum=0;105             dfs(i,0,a[i].l);106             ans=(ans*sum)%mod;107             for(int j=a[i].l;j<=a[i].r;j++)108             {109                 int x=find(e[j].u);110                 int y=find(e[j].v);111                 if(x!=y) p[x]=y;112             }113         }114         printf("%d\n",ans);115     }116     return 0;117 }

 

BZOJ 1016: [JSOI2008]最小產生樹計數

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.