• AtCoder Beginner Contest 266 E(期望) F(基环树)


    E - Throwing the Die(期望)
    题意
    掷骰子游戏,游戏有 N N N轮。每次掷骰子得到的数字就是分数,游戏可以随时终止,但不能超过 N N N轮,最后一次掷骰子得到的数字就是最终分数。给定 N N N的值,求期望分数的最大值。

    分析
    掷骰子得到分数的期望值与 N N N有关,用 f [ N ] f[N] f[N]表示游戏进行 N N N轮分数期望的最大值。由于题目所求的是期望的最大值,因此在第 N N N轮对于投出的每一种情况,期望值不能小于 f [ N − 1 ] f[N-1] f[N1],可得如下状态转移方程。
    f [ N ] = 1 6 ∑ i = 1 6 m a x ( i , f [ N − 1 ] ) f\lbrack N\rbrack=\frac16\sum_{i=1}^6max(i,f\lbrack N-1\rbrack) f[N]=61i=16max(i,f[N1])

    AC代码

    double f[N];
    int n;
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=6;j++)
    		{
    			f[i]+=max(j*1.0,f[i-1])/6;
    		}
    	}
    	cout<<fixed<<setprecision(6)<<f[n]<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    F - Well-defined Path Queries on a Namori(基环树 并查集 DFS)
    题意
    给定一个含有 N N N个点 N N N条边的无向连通图,问图上两个不同的点之间简单路径是否唯一。简单路径是图上不重复经过某个点的路径。

    分析
    根据题目中的定义可知给定的图是基环树,基环树上有且仅有一个环。如果将环上的边删去,就可以得到若干棵以环上的点为根的树。如果两个点之间的简单路径不唯一,那么这两个点之间的路径一定经过环上的边。将环断开后得到的每棵树可以看做是一个连通块,如果两个点在同一个连通块则简单路径唯一,否则不唯一。在实现时可以用并查集或者DFS,两种方法都是从度数为1的点入手,可以参考下面的代码。

    AC代码

    并查集

    const int N=2e5+10;
    vector<int> v[N];
    queue<int> q;
    int pa[N],in[N];
    int n,m;
    
    int find(int x)
    {
    	return pa[x]==x?pa[x]:pa[x]=find(pa[x]);
    }
    
    void merge(int x,int y)
    {
    	pa[find(x)]=pa[find(y)];
    }
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++) pa[i]=i;
    	for(int i=1;i<=n;i++)
    	{
    		int x,y;
    		cin>>x>>y;
    		v[x].push_back(y);
    		v[y].push_back(x);
    		in[x]++,in[y]++;
    	}
    	for(int i=1;i<=n;i++) if(in[i]==1) q.push(i);
    	while(q.size()>0)
    	{
    		int x=q.front();
    		q.pop();
    		for(auto y:v[x])
    		{
    			merge(x,y);
    			in[y]--;
    			if(in[y]==1) q.push(y);
    		}
    	}
    	cin>>m;
    	while(m--)
    	{
    		int x,y;
    		cin>>x>>y;
    		if(find(x)==find(y)) cout<<"Yes"<<endl;
    		else cout<<"No"<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    DFS

    vector<vector<int>> g;
    vector<bool> is_cycle;
    vector<int> root_id;
    
    void dfs(int v, int p) {
        root_id[v] = root_id[p];
        for(auto to : g[v]) {
            if(to != p) dfs(to, v);
        }
    }
    
    int main()
    {
        int n;
        cin >> n;
        g.resize(n);
        is_cycle.resize(n, true);
        root_id.resize(n, -1);
        vector<int> deg(n);
        for(int i = 0; i < n; i++) {
            int u, v;
            cin >> u >> v;
            --u, --v;
            g[u].push_back(v);
            g[v].push_back(u);
            deg[u]++, deg[v]++;
        }
        queue<int> que;
        for(int i = 0; i < n; i++) {
            if(deg[i] == 1) {
                que.push(i);
            }
        }
        while(!que.empty()) {
            int v = que.front();
            que.pop();
            is_cycle[v] = false;
            for(auto to : g[v]) {
                if(deg[to] >= 2) {
                    deg[to]--;
                    if(deg[to] == 1) {
                        que.push(to);
                    }
                }
            }
        }
        for(int i = 0; i < n; i++) {
            if(is_cycle[i]) {
                root_id[i] = i;
                for(auto to : g[i]) {
                    if(!is_cycle[to]) {
                        dfs(to, i);
                    }
                }
            }
        }
        int q;
        cin >> q;
        while(q--) {
            int u, v;
            cin >> u >> v;
            --u, --v;
            cout << (root_id[u] == root_id[v] ? "Yes" : "No") << endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
  • 相关阅读:
    什么是泛型,什么是泛型约束
    抄写Linux源码(Day16:内存管理)
    【STM32】定时器+基本定时器
    [23] T^3Bench: Benchmarking Current Progress in Text-to-3D Generation
    【LeetCode热题100】--2.两数相加
    msvcp120.dll缺失的解决方法与作用介绍
    MySQL事物
    [附源码]计算机毕业设计JAVAjsp大学生学业预警系统
    谷歌180nm 工艺芯片开源
    线性代数中涉及到的matlab命令-第三章:矩阵的初等变换及线性方程组
  • 原文地址:https://blog.csdn.net/weixin_46155777/article/details/126571588