博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
矩阵树定理
阅读量:4982 次
发布时间:2019-06-12

本文共 2978 字,大约阅读时间需要 9 分钟。

bzoj4031 小z的房间

题目大意:给定n*m的网格,有一些障碍点,求生成树的个数。

思路:矩阵树定理直接求解就可以了。但是因为要取模所以要稍微修改一下高斯消元,行列式交换行或列的时候行列式的值要变号。

#include
#include
#include
#include
#define p 1000000000#define LL long long#define maxm 105using namespace std;char map[maxm][maxm];int dx[4]={
1,0,-1,0},dy[4]={
0,1,0,-1},bi[maxm][maxm]={
0};LL ai[maxm][maxm]={
0};char in(){ char ch; while(scanf("%c",&ch)==1){ if (ch=='.'||ch=='*') return ch; }}int work(int n){ int i,j;LL x,y,k,ans=1,f=1,t; for (i=1;i<=n;++i) for (j=1;j<=n;++j) ai[i][j]=(ai[i][j]+p)%p; for (i=1;i<=n;++i){ for (j=i+1;j<=n;++j){ x=ai[i][i];y=ai[j][i]; while(y!=0){ k=x/y;x%=y;swap(x,y);f=-f; for (t=i;t<=n;++t) ai[i][t]=(ai[i][t]-k*ai[j][t]%p+p)%p; for (t=i;t<=n;++t) swap(ai[i][t],ai[j][t]); } }if (!ai[i][i]) return 0; ans=ans*ai[i][i]%p; }return (int)(ans*f%p+p)%p;}int main(){ int n,m,i,j,k,x,y,tot=0,u,v;scanf("%d%d",&n,&m); for (i=1;i<=n;++i){ for (j=1;j<=m;++j){map[i][j]=in();if (map[i][j]=='.') bi[i][j]=++tot;} }for (i=1;i<=n;++i) for (j=1;j<=m;++j){ if (map[i][j]!='.') continue; for (k=0;k<4;++k){ x=i+dx[k];y=j+dy[k]; if (x<1||x>n||y<1||y>m||map[x][y]!='.') continue; u=bi[i][j];v=bi[x][y]; ++ai[u][u];--ai[u][v]; } }printf("%d\n",work(tot-1));}
View Code

 

bzoj3534 重建(!!!

题目大意:给定n个城市和他们之间边通行概率,求通行道路恰是生成树的概率。

思路:设矩阵树的数组是G,G[i][j]=Pe/(1-Pe),G[i][i]=-sigma G[i][j],ci=∏(1-Pe),所以G的n-1阶主子式*tmp就是答案了。

其实原来矩阵树定理中邻接矩阵的1的意义可以看做是概率,这里的是Pe,但并不能简单的改为Pe,而是Pe/(1-Pe),因为可以发现这样G的主子式是sigma(T)∏(e∈T)Pe/(1-Pe),乘上ci之后,不是树边的相当于乘了(1-Pe),是树边的相当于乘了Pe正好是我们想要(一棵生成树的概率就是树边概率*(1-非树边概率))的答案。

#include
#include
#include
#include
#include
#define N 55#define eps 1e-9#define LD doubleusing namespace std;LD ai[N][N]={
0.},ci;int n;int cmp(LD x,LD y){ if (x-y>eps) return 1; if (y-x>eps) return -1; return 0;}LD gauss(){ int i,j,k;LD x;--n; for (i=1;i<=n;++i){ if (cmp(ai[i][i],0.)==0) for (j=i+1;j<=n;++j) if (cmp(ai[j][i],0.)!=0){ for (k=1;k<=n;++k) swap(ai[i][k],ai[j][k]); break;} for (j=i+1;j<=n;++j){ if (cmp(ai[j][i],0.)==0) continue; x=ai[j][i]/ai[i][i]; for (k=i;k<=n;++k) ai[j][k]-=ai[i][k]*x; } }for (x=1.,i=1;i<=n;++i) x*=ai[i][i]; return fabs(x);}int main(){ int i,j;scanf("%d",&n); for (ci=1.,i=1;i<=n;++i) for (j=1;j<=n;++j){ scanf("%lf",&ai[i][j]); if (i==j) continue; if (ai[i][j]>1.-eps) ai[i][j]-=eps; if (i
View Code

 

转载于:https://www.cnblogs.com/Rivendell/p/4856173.html

你可能感兴趣的文章
在Android8.0以上收不到广播问题(AppWidget)
查看>>
SCOI2010 传送带 [三分/模拟退火]
查看>>
C#读取文件,返回字符串形式的文件内容
查看>>
卸载软件时出现的“不能够打开文件INSTALL.LOG”错误-清理注册表即可
查看>>
R学习笔记(3):绘图
查看>>
类的封装
查看>>
命名空间的定义
查看>>
Android 中Json解析的几种框架(Gson、Jackson、FastJson、LoganSquare)使用与对比
查看>>
byte[]与各种数据类型互相转换示例
查看>>
swift 自定义TabBarItem
查看>>
Android 仿网易新闻v3.5:上下滑动的引导页
查看>>
php解析二维码
查看>>
Fragment 的生命周期及使用方法详解
查看>>
注意错误zoj2110-Tempter of the Bone
查看>>
Android中级第八讲--安卓子线程,以及定时任务使用讲解
查看>>
一对多的两个表,查询主表的信息和主表在子表中的记录条数
查看>>
主题演讲:未来新趋势电动车
查看>>
常用DNS列表(电信、网通)
查看>>
LeetCode-178:分数排名
查看>>
转:退火算法 Simulate Anneal Arithmetic (SAA,模拟退火算法)
查看>>