bzoj4637:期望

思路:最小生成树计数只不过加了一个期望,由于期望具有线性性质,就可以转化为每条边的期望之和,那么一条边的期望如何求呢,在最小生成树记数中,是把相同边权的一起处理,之后把属于连通块内的点缩点,也就是说,一条边只可能在它属于的连通块内对答案产生贡献,之后因为缩点而不会影响答案,因此一条边的期望就等于它在它所属的连通块内包含它的生成树个数除以那个连通块的生成树个数,而包含这条边的生成树个数就是该连通块内所有的生成树个数减去不包含这条边的生成树个数,然后用matrix-tree定理统计答案即可,因为这题要枚举边,所以最好写两个并查集,反正我之前的dfs写法没法写。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
#define maxm 200005
#define maxn 10005
const long double eps=1e-9;

int n,m,cnt,top;
int pos[maxn],stack[maxn];
bool instack[maxn];
long long tot;
long double ans,K[1000][1000],T[1000][1000];

vector<int> v[maxn];

struct edge{
    int from,to,dis,val;
    bool operator <(const edge &a)const{return dis<a.dis;}
}e[maxm];

inline int read(){
    int x=0;char ch=getchar();
    for (;ch<‘0‘||ch>‘9‘;ch=getchar());
    for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘;
    return x;
}

struct union_find_set{
    int fa[maxn];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
}u1,u2;

long long gauss(){
    int t,n=cnt-1,f=1;long double ans=1;
    for (int i=1;i<n;i++){
        for (t=i;t<=n;t++) if (fabs(K[t][i])>eps) break;if (t>n) return 0;
        if (t!=i){for (int j=1;j<=n;j++) swap(K[i][j],K[t][j]);f=-f;}
        for (int j=i+1;j<=n;j++)
            if (fabs(K[j][i])>eps){
                long double t=K[j][i]/K[i][i];
                for (int k=i;k<=n;k++) K[j][k]-=K[i][k]*t;
            }
    }
    for (int i=1;i<=n;i++) ans=ans*K[i][i];
    return round(ans*f);
}

void add(int x,int y,int val){
    K[x][y]-=val,K[y][x]-=val;
    K[x][x]+=val,K[y][y]+=val;
}

int main(){
    n=read(),m=read();
    for (int i=1;i<=m;i++) e[i].from=read(),e[i].to=read(),e[i].dis=read(),e[i].val=read();
    for (int i=1;i<=n;i++) u1.fa[i]=u2.fa[i]=i; sort(e+1,e+m+1);
    for (int i=1,l=1;i<=m+1;i++){
        int x=u1.find(e[i].from),y=u1.find(e[i].to);
        if (x!=y){int u=u2.find(x),v=u2.find(y);if (u!=v) u2.fa[u]=v;}
        if (e[i].dis!=e[i+1].dis){
            for (int j=l;j<=i;j++){
                int x=u1.find(e[j].from),y=u1.find(e[j].to);
                if (x==y) continue; int u=u2.find(x);
                if (!instack[u]) stack[++top]=u,instack[u]=1;
            }
            while (top){
                instack[stack[top]]=0,cnt=0;
                for (int j=l;j<=i;j++){
                    int x=u1.find(e[j].from),y=u1.find(e[j].to);
                    if (x==y) continue; int u=u2.find(x);
                    if (u==stack[top]){
                        if (!pos[x]) pos[x]=++cnt;
                        if (!pos[y]) pos[y]=++cnt;
                        add(pos[x],pos[y],1);
                    }
                }
                for (int a=1;a<=cnt;a++)
                    for (int b=1;b<=cnt;b++)
                        T[a][b]=K[a][b];
                tot=gauss();
                for (int a=1;a<=cnt;a++)
                    for (int b=1;b<=cnt;b++)
                        K[a][b]=T[a][b];
                for (int j=l;j<=i;j++){
                    int x=u1.find(e[j].from),y=u1.find(e[j].to);
                    if (x==y) continue; int u=u2.find(x);
                    if (u==stack[top]){
                        for (int a=1;a<=cnt;a++)
                            for (int b=1;b<=cnt;b++)
                                T[a][b]=K[a][b];
                        add(pos[x],pos[y],-1);
                        long long tmp=gauss();
                        for (int a=1;a<=cnt;a++)
                            for (int b=1;b<=cnt;b++)
                                K[a][b]=T[a][b];
                        ans+=1.0*(tot-tmp)/tot*e[j].val;
                    }
                }
                for (int j=l;j<=i;j++){
                    int x=u1.find(e[j].from),y=u1.find(e[j].to);
                    if (x==y) continue;pos[x]=pos[y]=0;
                }
                for (int j=1;j<=cnt;j++)
                    for (int k=1;k<=cnt;k++)
                        K[j][k]=0;
                top--;
            }
            for (int j=l;j<=i;j++){
                int x=u1.find(e[j].from),y=u1.find(e[j].to);
                if (x==y) continue;u1.fa[x]=y;
            }
            l=i+1;
        }
    }
    printf("%.5lf",(double)ans);
    return 0;
}
时间: 2024-08-08 18:17:07

bzoj4637:期望的相关文章

对软件工程课程的期望

学习到的能力预期: 1.首先,尽量能学会书中大部分知识,并能掌握和运用. 2.能体会到团队协作时互帮互助的乐趣和团队合作的重要性. 3..通过项目掌握更多的编程知识,加强自己的编程能力. 4.能在项目的基础上添加一些自己的功能. 对项目课程的期望: 1.希望做的项目可以激发我对编程的乐趣. 2.最好能完美做出给的项目. 对项目的愿景规划: 1.项目可以成功完成并且得到好的评价 2.每个成员都可以有所收获 3.每个人能提高自己的编程能力 4.没争执最好,有争执更能体现出每个人的学习态度.

《对软件工程课程的期望》

实践项目完成后学习到的能力的预期: 1. 能合理运用书本上的知识,不在是理论上的知识. 2. 提升自己的水平. 3. 与队友合作,取长补短,发挥长处,弥补不足. 对项目课程的期望: 1. 不要太难 2. 快乐学习 3. 学好,学精 对项目的愿景规划: 1.开发出的安卓具有: (1)实用且对大家都有帮助 (2)让用户有好的体验,比如界面和功能 (3)好玩,并且大家都喜欢用 2)每个成员体会到自己做出的软件的价值,能够有所收获. 3)拥有解决问题的体现. 4)每个人都有自己的价值,发挥自己的长处,弥

lightoj1027(数学期望与概率)

题意: 你在一个迷宫里,面前有n扇们,每个门有一个数字k; 如果k为正数,则通过这扇门,走k分钟就能出去, 如果为负数,则通过这扇门走-k的分钟回到迷宫; 走每扇门概率一样.问走出迷宫所需时间的期望值; 思路: 首先如果全是负数肯定是inf; 然后我们假设我们走出去的期望时间是d; 那么拿第三个样例举例子; d = 1/3 * 3  + 1/3( 6 + d) + 1/3 (9 + d); 意思就是每扇门被选择的概率是1/3;选选第一扇门要花3分钟出去,选第二扇门要6 + d(花6分钟返回原地,

HDU-4438 Hunters 期望 水

最近在复习概率DP求期望,顺便做一下. 分成第二个人选择老虎或者狼的情况. 然后 s1+=q*(p)*(p)*(x+y)+q*p*(1-p)*x+q*(1-p)*p*y;//老虎 且第一个人选择老虎的期望 s1+=(1-q)*x;//老虎 且第一个人选择狼的期望 求一下取大的输出就好.

数学期望

数学期望又称均值(加权均值),例如 甲8环,9环,10环的概率分别为0.1,0.8,0.1,即权重,则加权均值为8*0.1+9*0.8+10*0.1=9:同理乙的加权均值为8.95 则甲的平均成绩优于乙 对于离散型随机变量 连续型随机变量

了解移动用户的隐私期望:一种基于推荐的Crowdsourcing方法

应学习之需,最近一段时间阅读了一篇论文,特写下总结,若有纰漏,还望指出. 目录 引言 推荐机制 1.1 为什么要了解移动用户的隐私期望 1.移动设备的广泛使用存在一些潜在的隐私威胁和信息泄漏. 2.系统供应商针对这个问题已经提出了相应措施,例如:苹果的iOS系统可以让用户控制应用是否可以访问特定的敏感数据源.Android平台同样也有类似的细粒度权限控制机制.然而,存在自身缺点:不包括所有的用户都具备知识背景能够正确地进行隐私配置.同时是一项乏味且具有挑战性的工作.用户体验不高. 3.没有一个简

数学1——概率与数学期望

1.什么是数学期望? 数学期望亦称期望.期望值等.在概率论和统计学中,一个离散型随机变量的期望值是试验中每一次可能出现的结果的概率乘以其结果的总和. 这是什么意思呢?假如我们来玩一个游戏,一共52张牌,其中有4个A.我们1元钱赌一把,如果你抽中了A,那么我给你10元钱,否则你的1元钱就输给我了.在这个游戏中,抽中的概率是$\frac{1}{13} ( \frac{4}{52} ) $,结果是赢10元钱:抽不中概率是$\frac{12}{13}$,结果是亏1元钱.那么你赢的概率,也就是期望值是$-

[BZOJ 1076][SCOI2008]奖励关(期望+状压Dp)

Description 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物, 每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再吃).  宝物一共有n种,系统每次抛出这n种宝物的概率都相同且相互独立.也就是说,即使前k-1次系统都抛出宝物1( 这种情况是有可能出现的,尽管概率非常小),第k次抛出各个宝物的概率依然均为1/n. 获取第i种宝物将得到Pi 分,但并不是每种宝物都是可以随意获取的.第i种宝物有一个前

【bzoj4872】[Shoi2017]分手是祝愿 数论+期望dp

题目描述 Zeit und Raum trennen dich und mich. 时空将你我分开. B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态,下标为从 1 到 n 的正整数.每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示这个灯是灭的,游戏的目标是使所有灯都灭掉.但是当操作第 i 个开关时,所有编号为 i 的约数(包括 1 和 i)的灯的状态都会被改变,即从亮变成灭,或者是从灭变成亮.B 君发现这个游戏很难,于是想到了这样的一个