NC50772 B题(极简)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

有一个连通图 包含 n 个点 n 条无向边 其中每个点都与其他的两个点直接相连 (即这是一个环)
现在这个环的边变成了有向边 变成了有向边后得到的有向图不一定是强连通的 
(强连通图是指一个有向图中任意两点v1、v2间存在v1到v2的路径及v2到v1的路径的图)

所以现在给出 n 条有向边和把某条有向边转换方向后的代价, 问要使输入的有向图变成一个强连通图
例如输入
3
1 3 1
1 2 1
3 2 1
表示有一条有向边 1 -> 3 如果把这条边变成 3 -> 1 的代价是 1
表示有一条有向边 1 -> 2 如果把这条边变成 2 -> 1 的代价是 1
表示有一条有向边 3 -> 2 如果把这条边变成 2 -> 3 的代价是 1
对于输入的这个有向图是不存在 2 -> 3 的路径的 所以可以把 有向边 1 -> 2 变为 2 -> 1 这样图中任意两点均相互可达

输入描述:

多组测试数据。

第一行给出数字n,代表顶点数量 (3 ≤ n ≤ 100)。

接下来n行给出路径。

每行给出三个数字ai, bi, ci (1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ ci ≤ 100) — 代表ai指向bi。代价是ci。

输出描述:

输出最小代价

示例1

输入

3
1 3 1
1 2 1
3 2 1
3
1 3 1
1 2 5
3 2 1
6
1 5 4
5 3 8
2 4 15
1 6 16
2 3 23
4 6 42

输出

1
2
39

思路:每一个点都和其他两个点相连,易看出这些点必然组成一个环。题目让求的就是把这个环变成顺时针所需要的代价小,还是变成逆时针所需要的代价小。

首先,利用dfs还原这个环,给环中每一个点按环中的顺序编上号。然后顺时针、逆时针枚举,看那个所需代价小即可。

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N=110;

int n;
int a[N][N];
int snum[N],s;//snum存储环中每个点的序号 
bool vis[N];

void dfs(int u)
{
	vis[u]=1;
	snum[s++]=u;
	for(int i=1;i<=n;i++)
	{
		if(!vis[i]&&(a[i][u]||a[u][i]))
			dfs(i);
	}
}

int main()
{
//	freopen("input.txt","r",stdin);
	
	while(cin>>n)
	{
		s=0;
		memset(a,0,sizeof a);
		memset(snum,0,sizeof snum);
		memset(vis,0,sizeof vis);
		for(int i=0;i<n;i++)
		{
			int x,y,e;
			cin>>x>>y>>e;
			a[x][y]=e;
		}
		dfs(1);
		snum[s]=1;
		int ans1=0,ans2=0;
		for(int i=0;i<n;i++) ans1+=a[snum[i]][snum[i+1]];
		for(int i=n;i>=1;i--) ans2+=a[snum[i]][snum[i-1]];
		cout<<min(ans1,ans2)<<endl;
	}
	
	return 0;
 } 

参考博客:https://blog.csdn.net/cyendra/article/details/8772903

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章