bzoj3143 luogu3232 游走

Posted w19567

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3143 luogu3232 游走相关的知识,希望对你有一定的参考价值。

3143: [Hnoi2013]游走

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4289  Solved: 2008
[Submit][Status][Discuss]

Description

一个无向连通图,顶点从1编号到N,边从1编号到M。 
小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 
现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

Input

第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。

Output

仅包含一个实数,表示最小的期望值,保留3位小数。

Sample Input

3 3
2 3
1 2
1 3

Sample Output

3.333

HINT

 

边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
 
 
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m;
int mp[N][N],deg[N];
double mt[N][N],dp[N];
struct edge

    int s,t;
e[N*N];
void solve(int now)

    if(now==n) return;
    if(mt[now][now]==0)
    
        for(int i=now+1;i<n;++i)
            if(mt[i][now]!=0)
            
                for(int j=now;j<=n+1;++j)
                    swap(mt[now][j],mt[i][j]);
                break;
            
    
    for(int i=now+1;i<n;++i)
    
        double tmp=-mt[i][now]/mt[now][now];
        for(int j=now;j<=n+1;++j)
            mt[i][j]+=tmp*mt[now][j];
    
    //print();
    solve(now+1);
    dp[now]=mt[now][n+1]/mt[now][now];
    //cout<<dp[now]<<endl;
    for(int i=now-1;i>=1;--i) mt[i][n+1]-=dp[now]*mt[i][now];

bool cmp(edge u,edge v)

    return dp[u.s]+dp[u.t]>dp[v.s]+dp[v.t];

int main()

    int cnt=0;
    scanf("%d%d",&n,&m);
    memset(mp,-1,sizeof(mp));
    for(int i=1;i<=m;++i)
        
        int a,b;
        scanf("%d%d",&a,&b);
        e[i].s=a,e[i].t=b;
        mp[a][b]=mp[b][a]=1;
        ++deg[a],++deg[b];
    
    mt[1][n+1]=-1.0;
    for(int i=1;i<n;++i)
        for(int j=1;j<=n;++j)
        
            if(i==j) mt[i][i]=-1.0;
            if(mp[i][j]<0) continue;
            ++cnt;
            mt[i][j]=1.0/(double)deg[i];
        
    //print();
    solve(1);
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;++i)
    
        mp[e[i].s][e[i].t]=mp[e[i].t][e[i].s]=i;
    //    cout<<e[i].s<<" "<<e[i].t<<endl;
    
    for(int i=1;i<n;++i)
        for(int j=1;j<=n+1;++j)
            mt[i][j]=0.0;
    for(int i=1;i<n;++i)
        for(int j=1;j<=n;++j)
        
            if(i==j) mt[i][i]=-1.0;
            if(mp[i][j]<0) continue;
            ++cnt;
            mt[i][j]=1.0/(double)deg[i];
            mt[i][n+1]-=(double)mp[i][j]/deg[i];
        
    solve(1);
    printf("%.3lf",dp[1]);
    return 0;

 

以上是关于bzoj3143 luogu3232 游走的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3232 [HNOI2013]游走

BZOJ 3143: [Hnoi2013]游走

bzoj3143 游走

BZOJ-3143游走 高斯消元 + 概率期望

bzoj3143游走

BZOJ3143:[Hnoi2013]游走——题解