本蒟蒻又卡题了!!

题目描述

小埋最近在学习有向图的遍历相关知识,小埋学习过图的遍历的相关方法,可以使用dfs或者bfs来遍历整个有向图,但是小埋发现这个问题有一些不一样,这个图的遍历是问你当前点能够到达的点的最大编号,小埋希望你能帮她解决这个问题。

输入格式

第一行两个整数一个n一个m,n代表有向图中有n个点,m代表有向图中有m条有向边。接下来是m条边。

输出格式

输出每个点能够到达的最大编号

样例

Input 1

4 3 1 2 1 3 2 3

Output 1

3 3 3 4

样例解释

样例1解释:
对于样例1,有向图如下所示:
1 → 2
| |
v v
3
|
v
4
从1开始,可以到达的最大编号是3,从2开始,可以到达的最大编号是3,从3开始,可以到达的最大编号是3,从4开始,可以到达的最大编号是4。

数据范围

数据范围:1<=n,m<=100000

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

const int MAXN = 100001;

vector<int> adj[MAXN];
bool visited[MAXN];
int max_reachable[MAXN];

void dfs(int node, int& max_index) {
	stack<int> stk;
	stk.push(node);
	visited[node] = true;

	while (!stk.empty()) {
		int curr = stk.top();
		stk.pop();

		for (int neighbor : adj[curr]) {
			if (!visited[neighbor]) {
				visited[neighbor] = true;
				stk.push(neighbor);
				max_reachable[neighbor] = max(max_reachable[neighbor], max_reachable[curr]);
				max_index = max(max_index, max_reachable[neighbor]);
			}
		}
	}
}

int main() {
	int n, m;
	cin >> n >> m;

	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		adj[u].push_back(v);
	}

	for (int i = 1; i <= n; ++i) {
		visited[i] = false;
		max_reachable[i] = i; 
	}

	for (int i = 1; i <= n; ++i) {
		if (!visited[i]) {
			int max_index = i;
			dfs(i, max_index);
			max_reachable[i] = max_index; 
		}
	}

	for (int i = 1; i <= n; ++i) {
		cout << max_reachable[i] << " ";
	}
	cout << endl;

	return 0;
}

题目描述

小埋最近经营n个农场,小埋要各个农场都有w个员工,每个农场也有一个编号,现在要在某个农场内建立一个物资站,使得所有员工到物资站的路程之和尽可能的小,同时约定,相邻点之间的距离为1。如上图中,若物资站建在1处,则距离和=4+12+2×20+2×40=136;若物资站建在3处,则距离和=4×2+13+20+40=81。

输入格式

第一行输入一个整数n
第二行n个数字,每个数字wi,代表每个农场的员工。
以下n-1行每行输出两个农场的编号,u,v,uv之间是双向边。

输出格式

输出一个整数,代表农场的最小距离和。

样例

Input 1

5 13 4 12 20 40 1 2 1 3 3 4 3 5

Output 1

81

样例解释

样例1解释:
物资站建在3处,距离和=4×2+13+20+40=81。

数据范围

1<=n<=100;

1<=u,v<=n;

1<=w<=1e5

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 105;
vector<int> adj[MAXN];
int w[MAXN];
int dp[MAXN][2]; 
void dfs(int u, int parent) {
    dp[u][0] = w[u];
    dp[u][1] = 0;  
    for (int v : adj[u]) {
        if (v == parent) continue; /

        dfs(v, u);

        dp[u][0] += dp[v][1];

   
        dp[u][1] += min(dp[v][0], dp[v][1]);
    }
}

int main() {
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        cin >> w[i];
    }

    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1, -1);
    cout << min(dp[1][0], dp[1][1]) << endl;

    return 0;
}

6 个赞

@Syxqwq @周子寓 @王梓涵

6 个赞

解释一下你第二题的思路

5 个赞

我的思路是将每个点作为物资站
一个一个搜索试取最低的

5 个赞

而第一题
我们可以反向存边
然后从大的开始遍历
遍历到的最大值就是它
给你个伪代码

#include<bits/stdc++.h>
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100001];
vector<int>v[100001];
void dfs(int x,int y)
{
	/*x能遍历的最大值就是y了*/
	for(int i=0;i<v[x].size();++i)
	if(/*没被更大的数遍历过*/)
	{
		//继续遍历 
	}
}
int main()
{
	//a数组记录它能遍历到的最大点 
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		/*这里反向存边*/
	}
	for(int i=n;i>=1;--i)
	if(!a[i]) dfs(i,i);//没被更大的数遍历过 
	//输出 
	return 0;
}
5 个赞

嗯嗯,谢大佬

6 个赞

无思路,按照感觉做

5 个赞

我乍一看感觉你搞了个树形dp

4 个赞

确实

5 个赞

第二题还是不对

#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 100001;
vector<int> v[MAXN];
int n, m, a[MAXN];

void dfs(int x, int y) {
    a[x] = y; 

    for (int i = 0; i < v[x].size(); ++i) {
        int next = v[x][i];
        if (a[next] == 0) {
            dfs(next, y); 
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        v[y].push_back(x); 
    }

    for (int i = n; i >= 1; --i) {
        if (a[i] == 0) {
            dfs(i, i);
        }
    }
    for (int i = 1; i <= n; ++i) {
        printf("%d ", a[i]);
    }

    return 0;
}

5 个赞

第二题是个换根 dp。

6 个赞

哦.

5 个赞

语法进阶->算2算3一起上->暑假普2

5 个赞

现在放假,4天干完普1

4 个赞

只剩这两道题了

4 个赞

多少分

4 个赞
4 个赞

参考一下这题 [ABC220F] Distance Sums 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

5 个赞

4 个赞

嗯.

4 个赞