bzoj1016

来源:互联网 发布:淘宝没发货退款要多久 编辑:程序博客网 时间:2024/06/05 09:42

噗~  其实目前的想法的话 是跟着Aekdycoin神的脚步 开始坚持把bzoj继续刷下去·· 其实我并不知道自己还能坚持多久了啦不过凡事都要尽力而为  所以只是记下一些稍微重要的题目,用来作为一个类似备忘录 的作用吧!

题目的话在bzoj上面:http://www.lydsy.com/JudgeOnline/problem.php?id=1016

大概的题意就是:求一个图的最小生成树个数~


这里要用到主要的一个东西就是··~  

1、边权相等的边的个数一定。

2、做完边权为w的所有边时,图的连通性相同。

因此  可以通过这个性质先求出该图的最小生成树··~  记录下各个边权的个数,之后的话因为条件2,对边权大小进行枚举~

将求出的最小生成树中除了枚举边权以外的边全部连上~ 并查集缩点

之后从原图中找出与枚举边权相同的边~ 对于缩点之后的图进行连边~  再用一次拉普拉斯矩阵 求生成树个数就可以啦

关于拉普拉斯矩阵:http://en.wikipedia.org/wiki/Laplacian_matrix

简单地说就是 拉普拉斯矩阵=度数矩阵-邻接矩阵  对于该矩阵去掉一行一列求其行列式的值 就是生成树个数


对于每个边权都求出等价连通性的边连法  乘法定理走起~ 求出最终答案!


我只是按自己的理解来写了啦不过应该是实现方法比较挫 导致写了好长 代码风格是时候改一下啦看到人家写的2000B不到的代码各种羡慕Otz


//============================================================================// Name        : bzoj1016.cpp// Author      : // Version     :// Copyright   : Your copyright notice// Description : Hello World in C++, Ansi-style//============================================================================#include <iostream>#include<string>#include<cstdio>#include<cstring>#include<algorithm>#define MOD 31011#define N 105using namespace std;struct node{int ui,vi,val;};node edge[2005];int cmp(node a,node b){if (a.val!=b.val)return (a.val<b.val);return (a.ui<b.ui);}int cnt;int fah[105];int que[2005];int cntq;int getfather(int x){if (x!=fah[x])fah[x]=getfather(fah[x]);return (fah[x]);}int det(int a[][N],int n)//生成树计数:Matrix-Tree定理{    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)            a[i][j]%=MOD;    int ret=1;    for(int i=1; i<n; i++)    {        for(int j=i+1; j<n; j++)            while(a[j][i])            {                int t=a[i][i]/a[j][i];                for(int k=i; k<n; k++)                    a[i][k]=(a[i][k]-a[j][k]*t)%MOD;                for(int k=i; k<n; k++)                    swap(a[i][k],a[j][k]);                ret=-ret;            }        if(a[i][i]==0)            return 0;        ret=ret*a[i][i]%MOD;    }    if(ret<0)        ret=-ret;    return (ret+MOD)%MOD;}int bin_sl(int now){int b_l=0,b_r=cnt-1;while (b_r-b_l>1){int b_mid=(b_l+b_r)>>1;if (edge[b_mid].val>=now)b_r=b_mid;elseb_l=b_mid;}if (edge[b_l].val==now) return(b_l);return (b_r);}int bin_sr(int now){int b_l=0,b_r=cnt-1;while (b_r-b_l>1){int b_mid=(b_l+b_r)>>1;if (edge[b_mid].val>now)b_r=b_mid;elseb_l=b_mid;}if (edge[b_r].val==now) return (b_r);return (b_l);}int n,m;int main() {scanf("%d%d",&n,&m);cnt=-1;for (int i=0;i<m;i++){cnt++;scanf("%d%d%d",&edge[cnt].ui,&edge[cnt].vi,&edge[cnt].val);edge[cnt].ui--;edge[cnt].vi--;cnt++;edge[cnt].ui=edge[cnt-1].ui;edge[cnt].vi=edge[cnt-1].vi;edge[cnt].val=edge[cnt-1].val;}cnt++;sort(edge,edge+cnt,cmp);for (int i=0;i<n;i++) fah[i]=i;cntq=0;for (int i=0;i<cnt;i++){int nowx,nowy;nowx=getfather(edge[i].ui);nowy=getfather(edge[i].vi);if (nowx!=nowy){fah[nowx]=nowy;que[cntq++]=i;}}int li,ri;int ans=1;li=ri=0;//cout<<cntq<<endl;/*for (int i=0;i<cntq;i++)printf("node1-->%d node2-->%d nodeval-->%d\n",edge[que[i]].ui,edge[que[i]].vi,edge[que[i]].val);*/while (li<cntq){while (ri<cntq && edge[que[li]].val==edge[que[ri]].val) ri++;ri--;//cout<<"ri="<<ri<<endl;for (int i=0;i<n;i++) fah[i]=i;for (int i=0;i<cntq;i++)if (i<li || i>ri){int nowx,nowy;nowx=getfather(edge[que[i]].ui);nowy=getfather(edge[que[i]].vi);fah[nowx]=nowy;}int vised[105];int cntn=0;memset(vised,-1,sizeof(vised));for (int i=0;i<n;i++){int nowx=getfather(i);if (vised[nowx]==-1)vised[nowx]=cntn++;}int lf=bin_sl(edge[que[li]].val);int rf=bin_sr(edge[que[li]].val);int gra[N][N];memset(gra,0,sizeof(gra));for (int i=lf;i<=rf;i++){int nowx,nowy;nowx=getfather(edge[i].ui);nowy=getfather(edge[i].vi);if (nowx!=nowy){gra[vised[nowx]][vised[nowx]]++;gra[vised[nowy]][vised[nowy]]++;gra[vised[nowx]][vised[nowy]]--;gra[vised[nowy]][vised[nowx]]--;}}for (int i=0;i<cntn;i++){for (int j=0;j<cntn;j++)gra[i][j]/=2;}ans=ans*det(gra,cntn);ans%=MOD;ri=li=ri+1;//cout<<"li="<<li<<endl;}printf("%d\n",ans);return 0;}


0 0