2019 ICPC 南京网络赛 D.Robots

2019 ICPC 南京网络赛 D.Robots


题目给出n个点和m条有向边,机器人从1走到n,询问消耗的能量的期望。

如果只是求1到n的期望天数,就是很简单的套路题了,设dp[i]表示从i走到n的期望天数,容易得到dp[i]=p*dp[i]+(1-p)*dp[j]+1,其中p表示原地不动的概率。

比赛的时候求出天数之后就不会做了,没有细想,其实再叠加一曾,再做一次就可以了,设能量消耗是cost[i],一样有一个方程cost[i]=p *cost[i]+(1-p)*cost[j]+dp[i];

同样的方法做两次,服了。

写的时候利用拓扑,每次处理出度为0的点,一直处理到点1.

下面是AC代码:

#include <bits/stdc++.h>
using namespace std;
vector<int> a[100005];
vector<int> b[100005];
int vis1[100005];
int vis2[100005];
double dp[100005];
double cost[100005];
int main()
{
    
    

    int T;
    cin>>T;
    while(T--)
    {
    
    
        int n,m;
        scanf("%d%d",&n,&m);
        int j=1;while(j<=n)
        {
    
    
            a[j].clear();
            b[j].clear();
            vis1[j]=0;
            vis2[j]=0;
            dp[j]=0;
            cost[j]=0;
            j++;
        }
        int i=1;while(i<=m)
        {
    
    
            int x,y;
            scanf("%d%d",&x,&y);
            a[y].push_back(x);
            b[x].push_back(y);
            vis1[x]++;
            vis2[x]++;
            i++;
        }
        vector<int>tt;
        tt.push_back(n);
        while(tt.size())
        {
    
    
            int temp=tt[0];
            tt.erase(tt.begin());
            int t1=b[temp].size();
            if(t1==0) dp[temp]=0;
            else
            {
    
    
                double sum=0;
                int k=0;while(k<t1)
                {
    
    
                    sum=sum+dp[b[temp][k]];
                    k++;
                }
                dp[temp]=1.0*(sum+t1+1)/t1;
            }

            int k=0;while(k<a[temp].size())
            {
    
    
                vis1[a[temp][k]]--;
                if(vis1[a[temp][k]]==0)
                {
    
    
                    tt.push_back(a[temp][k]);
                }
                k++;
            }
        }
        tt.push_back(n);
        while(tt.size())
        {
    
    
            int temp=tt[0];
            tt.erase(tt.begin());
            int t1=b[temp].size();
            if(t1==0) cost[temp]=0;
            else
            {
    
    
                double sum=0;
                int k=0;while(k<t1)
                {
    
    
                    sum=sum+cost[b[temp][k]];
                    k++;
                }
                cost[temp]=1.0*(sum+(t1+1)*dp[temp])/t1;
            }

            int k=0;while(k<a[temp].size())
            {
    
    
                vis2[a[temp][k]]--;
                if(vis2[a[temp][k]]==0)
                {
    
    
                    tt.push_back(a[temp][k]);
                }
                k++;
            }
        }

        printf("%.2lf\n",cost[1]);


    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yzsjwd/article/details/100322384
今日推荐