拼多多笔试真题-多多捕蝇(C++/Py/Java /Js/Go)

多多捕蝇

拼多多技术岗 7月3号笔试 第三题

题目内容

现在多多宿舍区有 nnn 个房间(编号 111 到 nnn)和一只苍蝇,多多准备通过在房间放置粘蝇板的方式进行捕蝇,如果要在房间 iii 捕捉到苍蝇,需要在该房间放置 CiC_iCi 个粘蝇板。

苍蝇会在各个房间进行活动,如果它现在在房间 iii,下一分钟它会跑到房间 aia_iai(如果 i=aii = a_ii=ai,表示苍蝇不会离开房间),苍蝇所在的初始房间是随机不确定的,它可能初始出现在任意一个房间。

如果需要捕捉到这只苍蝇,请你帮多多计算下至少需要多少个粘蝇板。

输入描述

每个测试用例,第一行包含一个整数 nnn(1≤n≤1051 \le n \le 10^51≤n≤105),表示房间的数量;

第二行包含 nnn 个整数 c1,c2,...,cnc_1,c_2,...,c_nc1,c2,...,cn(1≤ci≤1041 \le c_i \le 10^41≤ci≤104),cic_ici 表示在房间 iii 捕捉到苍蝇需要的粘蝇板数量;

第三行包含 nnn 个整数 a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an(1≤ai≤n1 \le a_i \le n1≤ai≤n),aia_iai 表示在当前房间 iii 的苍蝇,下一分钟去到的房间。

输出描述

每个测试用例输出一个整数,表示多多捕捉到苍蝇需要的最少的粘蝇板数量。

样例1

输入

复制代码
4
1 10 2 10
2 4 2 2

输出

复制代码
10

说明

把粘蝇板放在第 222 个房间,无论苍蝇最开始出现在哪个房间,在经过一段时间之后都会通过第 222 个房间,所需要的粘蝇板数量就是 101010。

题解

思路

解决思路: 拓扑排序 + DFS

  1. 这道题本质是一个有向图,这个图有个特点就是所有节点要不属于某个环,要不指向一个环
  2. 接下来考虑怎么放置成本最低,分情况讨论
    • 位于环中,由于环中中节点全部可互相访问,一个环中最低成本就为环中最小min(c)
    • 指向环的节点,指向环的节点根本无需放置,可由指向环中节点帮忙捕获。利用A -> B -->C 把C看作一个环,覆盖这个块最低成本就是选择C。
  3. 根据2的分析,根本无需处理指向环的节点,这部分节点可通过拓扑排序进行剔除。成本由环决定,可通过递归处理接下来每个环,总成本为所有环中sum(min(c))

C++

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    vector<int> c(n + 1);
    vector<int> indeg(n + 1, 0);
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        indeg[a[i]]++;
    }
    
    
    queue<int> q;
    for (int i = 1; i <= n; i++) {
        if (indeg[i] == 0) {
            q.push(i);
        }
    }
    
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        int v = a[u];
        indeg[v]--;
        if (indeg[v] == 0) {
            q.push(v);
        }
    }
    long ans = 0;
    // 现在剩余的都是环
    vector<int> vis(n + 1, false);
    for (int i = 1; i <= n; i++) {
        if (indeg[i] > 0 && !vis[i]) {
            int current = i;
            int minCost = c[i];
            vis[i] = true;
            current = a[current];
            while (current != i) {
                minCost = min(minCost, c[current]);
                vis[current] = true;
                current = a[current];
            }
            ans += minCost;
        }
    }
    cout << ans;
    return 0;
}

java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(br.readLine());

        int[] a = new int[n + 1];
        int[] c = new int[n + 1];
        int[] indeg = new int[n + 1];

        String[] parts = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) {
            c[i] = Integer.parseInt(parts[i - 1]);
        }

        parts = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) {
            a[i] = Integer.parseInt(parts[i - 1]);
            indeg[a[i]]++;
        }

        Queue<Integer> q = new LinkedList<>();
        for (int i = 1; i <= n; i++) {
            if (indeg[i] == 0) {
                q.offer(i);
            }
        }

        while (!q.isEmpty()) {
            int u = q.poll();
            int v = a[u];
            indeg[v]--;
            if (indeg[v] == 0) {
                q.offer(v);
            }
        }

        long ans = 0;
        // 现在剩余的都是环
        boolean[] vis = new boolean[n + 1];

        for (int i = 1; i <= n; i++) {
            if (indeg[i] > 0 && !vis[i]) {
                int current = i;
                int minCost = c[i];
                vis[i] = true;
                current = a[current];

                while (current != i) {
                    minCost = Math.min(minCost, c[current]);
                    vis[current] = true;
                    current = a[current];
                }

                ans += minCost;
            }
        }

        System.out.println(ans);
    }
}

python

python 复制代码
import sys
from collections import deque

data = list(map(int, sys.stdin.read().split()))

n = data[0]
idx = 1

a = [0] * (n + 1)
c = [0] * (n + 1)
indeg = [0] * (n + 1)

for i in range(1, n + 1):
    c[i] = data[idx]
    idx += 1

for i in range(1, n + 1):
    a[i] = data[idx]
    indeg[a[i]] += 1
    idx += 1

q = deque()

for i in range(1, n + 1):
    if indeg[i] == 0:
        q.append(i)

while q:
    u = q.popleft()
    v = a[u]
    indeg[v] -= 1
    if indeg[v] == 0:
        q.append(v)

ans = 0

# 现在剩余的都是环
vis = [False] * (n + 1)

for i in range(1, n + 1):
    if indeg[i] > 0 and not vis[i]:
        current = i
        min_cost = c[i]
        vis[i] = True
        current = a[current]

        while current != i:
            min_cost = min(min_cost, c[current])
            vis[current] = True
            current = a[current]

        ans += min_cost

print(ans)

javascript

js 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on("line", (line) => {
    input.push(...line.trim().split(/\s+/));
});

rl.on("close", () => {
    let idx = 0;

    const n = Number(input[idx++]);

    const a = new Array(n + 1).fill(0);
    const c = new Array(n + 1).fill(0);
    const indeg = new Array(n + 1).fill(0);

    for (let i = 1; i <= n; i++) {
        c[i] = Number(input[idx++]);
    }

    for (let i = 1; i <= n; i++) {
        a[i] = Number(input[idx++]);
        indeg[a[i]]++;
    }

    const q = [];
    let head = 0;

    for (let i = 1; i <= n; i++) {
        if (indeg[i] === 0) {
            q.push(i);
        }
    }

    while (head < q.length) {
        const u = q[head++];
        const v = a[u];
        indeg[v]--;

        if (indeg[v] === 0) {
            q.push(v);
        }
    }

    let ans = 0;

    // 现在剩余的都是环
    const vis = new Array(n + 1).fill(false);

    for (let i = 1; i <= n; i++) {
        if (indeg[i] > 0 && !vis[i]) {
            let current = i;
            let minCost = c[i];

            vis[i] = true;
            current = a[current];

            while (current !== i) {
                minCost = Math.min(minCost, c[current]);
                vis[current] = true;
                current = a[current];
            }

            ans += minCost;
        }
    }

    console.log(ans);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	in := bufio.NewReader(os.Stdin)

	var n int
	fmt.Fscan(in, &n)

	a := make([]int, n+1)
	c := make([]int, n+1)
	indeg := make([]int, n+1)

	for i := 1; i <= n; i++ {
		fmt.Fscan(in, &c[i])
	}

	for i := 1; i <= n; i++ {
		fmt.Fscan(in, &a[i])
		indeg[a[i]]++
	}

	q := make([]int, 0)
	head := 0

	for i := 1; i <= n; i++ {
		if indeg[i] == 0 {
			q = append(q, i)
		}
	}

	for head < len(q) {
		u := q[head]
		head++

		v := a[u]
		indeg[v]--

		if indeg[v] == 0 {
			q = append(q, v)
		}
	}

	var ans int64 = 0

	// 现在剩余的都是环
	vis := make([]bool, n+1)

	for i := 1; i <= n; i++ {
		if indeg[i] > 0 && !vis[i] {
			current := i
			minCost := c[i]

			vis[i] = true
			current = a[current]

			for current != i {
				if c[current] < minCost {
					minCost = c[current]
				}
				vis[current] = true
				current = a[current]
			}

			ans += int64(minCost)
		}
	}

	fmt.Println(ans)
}
相关推荐
无限码力5 天前
拼多多笔试真题-多多的营救行动(C++/Py/Java /Js/Go)
拼多多·拼多多笔试真题·拼多多笔试题库·拼多多技术岗笔试
无限码力6 天前
拼多多笔试真题-对角线遍历矩阵(C++/Py/Java /Js/Go)
矩阵·拼多多·拼多多笔试真题·拼多多技术岗笔试题目·拼多多机试
27669582921 年前
拼多多小程序 anti_content 分析
java·javascript·python·node·拼多多·anti-content·anti_content
27669582921 年前
拼多多 anti-token unidbg 分析
java·python·go·拼多多·pdd·pxx·anti-token
市象2 年前
独家|安克Temu平台闭店,或遭遇亚马逊“二选一”
亚马逊·temu·拼多多
诗雅颂2 年前
【js逆向学习】某多多anti_content逆向(补环境)
开发语言·javascript·webpack·逆向·拼多多·补环境·anti_content
软件、小程序、网站、脚本开发商2 年前
拼多多商品全流程自动化采集
大数据·金融·自动化·制造·零售·教育电商·拼多多
老谭聊跨境2 年前
2024年已过半,靠独立站赚钱行得通吗?
跨境电商·外贸·拼多多·独立站·海外掘金
爱python的王三金3 年前
【temu】分析拼多多跨境电商Temu数据分析数据采集
爬虫·python·数据挖掘·数据分析·跨境电商·temu·拼多多