【DFS+题意】#24 A. Ring road

本文探讨了在交通网络中引入单向行驶后如何通过最小化成本重新定向道路以确保从任何一个城市到另一个城市的通行路径。通过算法实现,提供了解决方案以优化城市间的交通流动。

A. Ring road
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Nowadays the one-way traffic is introduced all over the world in order to improve driving safety and reduce traffic jams. The government of Berland decided to keep up with new trends. Formerly all n cities of Berland were connected by n two-way roads in the ring, i. e. each city was connected directly to exactly two other cities, and from each city it was possible to get to any other city. Government of Berland introduced one-way traffic on all n roads, but it soon became clear that it's impossible to get from some of the cities to some others. Now for each road is known in which direction the traffic is directed at it, and the cost of redirecting the traffic. What is the smallest amount of money the government should spend on the redirecting of roads so that from every city you can get to any other?

Input

The first line contains integer n (3 ≤ n ≤ 100) — amount of cities (and roads) in Berland. Next n lines contain description of roads. Each road is described by three integers aibici (1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ ci ≤ 100) — road is directed from city aito city bi, redirecting the traffic costs ci.

Output

Output single integer — the smallest amount of money the government should spend on the redirecting of roads so that from every city you can get to any other.

Sample test(s)
input
3
1 3 1
1 2 1
3 2 1
output
1
input
3
1 3 1
1 2 5
3 2 1
output
2
input
6
1 5 4
5 3 8
2 4 15
1 6 16
2 3 23
4 6 42
output
39
input
4
1 2 9
2 3 8
3 4 7
4 1 5
output
0

我还是想问,这个不是建立联系表么……为啥这道题要算作是dfs啊……还是说这个就是dfs的意思么……

这道题是要求形成一个单向环(最初吓了我一跳,还以为是图论题,吾辈最怕图论了……),后来发现……只需要一条路找下去,不行的就花钱逆回来,然后看看正着便宜还是倒着便宜就行了。


#include <map>
#include <stack>
#include <queue>
#include <cmath> 
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int  n=0,pos=0,ans1=0,ans2=0;
bool vis	[111];
int  chain	[111];
int  cost	[111][111];

#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))

void dfs(int now)// make a linked chain of nodes
{
	vis[now]=true;
	chain[pos++]=now;
	for(int k=1;k<=n;k++)// find next
	{
		if(vis[k]==false && (cost[k][now]>0 || cost[now][k]>0))
		dfs(k);
	}
}

int main()
{
	memset(cost,0,sizeof(cost));
	memset(vis,false,sizeof(vis));
	int total_cost=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		int _start=0,_end=0;
		scanf("%d%d",&_start,&_end);
		scanf("%d",&cost[_start][_end]);
		total_cost+=cost[_start][_end];
	}
	dfs(1);// start from 1,make a chain until 1 ends
	chain[pos]=1;// when end, we get back to 1
	for(int j=0;j<pos;j++)		ans1+= cost[chain[j]][chain[j+1]];
	for(int j=pos;j>=1;j--)		ans2+= cost[chain[j]][chain[j-1]];
	//cout<<total_cost<<endl<<ans1<<endl<<ans2<<endl;
	printf("%d",Min(ans1,ans2));
	return 0;
}



最大城镇面积问本质上是求二维网格中**连通块的最大大小**,其中上下左右相邻且颜色相同的格子视为连通。这是一个典型的图论中的连通性问,可以使用 **深度优先搜索(DFS)** 或 **广度优先搜索(BFS)** 来解决。 --- ###思路: 1. **输入处理**:读取 `n × m` 的字符矩阵。 2. **遍历每个格子**:对每一个未访问过的格子,启动一次 DFS,统计其所在连通区域(即“城镇”)的面积。 3. **标记已访问**:使用一个布尔数组 `visited` 记录是否访问过该格子,避免重复计算。 4. **DFS 搜索**: - 从当前格子出发,向四个方向(上、下、左、右)扩展。 - 只有当邻居格子与当前格子颜色相同且未被访问时才继续递归。 - 累加访问的格子数作为该城镇的面积。 5. **维护最大值**:每次 DFS 返回连通块大小,更新全局最大面积。 6. **输出结果**。 > 目提示使用 DFS + 剪枝,且不需要恢复现场 —— 这意味着我们只需通过 `visited` 数组跳过已处理的位置即可,无需回溯状态。 --- ### C++ 实现代码如下: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; // 方向数组:上、下、左、右 const int dx[4] = {-1, 1, 0, 0}; const int dy[4] = {0, 0, -1, 1}; // 全局变量 int n, m; vector<string> grid; vector<vector<bool>> visited; // DFS函数:从(x,y)开始遍历同色连通块,返回面积 int dfs(int x, int y, char color) { if (x < 0 || x >= n || y < 0 || y >= m || visited[x][y] || grid[x][y] != color) { return 0; } visited[x][y] = true; int area = 1; // 当前格子 for (int i = 0; i < 4; ++i) { int nx = x + dx[i]; int ny = y + dy[i]; area += dfs(nx, ny, color); } return area; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; grid.resize(n); visited.assign(n, vector<bool>(m, false)); for (int i = 0; i < n; ++i) { cin >> grid[i]; } int maxArea = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (!visited[i][j]) { int area = dfs(i, j, grid[i][j]); maxArea = max(maxArea, area); } } } cout << maxArea << endl; return 0; } ``` --- ### 解释: - **时间复杂度**:O(n × m),每个格子最多被访问一次。 - **空间复杂度**:O(n × m),用于存储网格和 `visited` 数组;递归栈最深可达 O(n×m)(极端情况下整个图是一个连通块)。 - 使用了剪枝:`visited` 和边界判断提前终止无效搜索。 - 不需要“恢复现场”是因为我们只关心每个格子是否已被计入某个城镇,不涉及路径回溯或状态切换。 --- ### 示例解析(样例输入): 输入为 9×11 的地图,其中 `&#39;.&#39;` 在右下角形成一大片连续区域,经过 DFS 发现其最大连通块面积为 **27**,对应输出。 例如,最后一行: ``` ++.#.#....# ``` 末尾有多个 `&#39;.&#39;`,向上多行也有大量 `&#39;.&#39;` 相连,最终构成面积为 27 的连通区域。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糖果天王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值