题目类型 简单题
题目意思
有一个连通图 包含 n 个点 n 条无向边 其中每个点都与其他的两个点直接相连 (即这是一个环)
现在这个环的边变成了有向边 变成了有向边后得到的有向图不一定是强连通的
(强连通图是指一个有向图中任意两点v1、v2间存在v1到v2的路径及v2到v1的路径的图)
所以现在给出 n 条有向边和把某条有向边转换方向后的代价, 问要使输入的有向图变成一个强连通图
例如输入
3
1 3 1
1 2 1
3 2 1
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 这样图中任意两点均相互可达
解题方法
可以发现 对于输入的有向图(不考虑边的方向的话原来是一个环) 要使它变成强连通的 那么它的边的方向一定是一致的
即如果不全是顺时针的就一定全是逆时针的, 所以对于两种情况计算一下代价就行了
参考代码
- 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 1e2 + 10;
vector<int>edge[MAXN];
vector<int>w[MAXN];
int main() {
int n;
while(scanf("%d", &n) != EOF) {
for( int i=1; i<=n; i++ ) edge[i].clear(), w[i].clear();
int a, b, c;
for( int i=0; i<n; i++ ) {
scanf("%d%d%d", &a, &b, &c);
edge[a].push_back(b);
w[a].push_back(c);
edge[b].push_back(a);
w[b].push_back(-c);
}
int res = 0;
int pre = 1;
int next = edge[1][0];
if(w[1][0] < 0) res += -w[1][0];
while(next != 1) {
//printf("next = %d\n", next);
int tmp = edge[next][0];
if(tmp == pre) {
tmp = edge[next][1];
if(w[next][1] < 0) res += -w[next][1];
pre = next;
next = tmp;
}
else {
if(w[next][0] < 0) res += -w[next][0];
pre = next;
next = tmp;
}
}
int t_res = 0;
pre = 1;
next = edge[1][1];
if(w[1][1] < 0) t_res += -w[1][1];
while(next != 1) {
int tmp = edge[next][0];
if(tmp == pre) {
tmp = edge[next][1];
if(w[next][1] < 0) t_res += -w[next][1];
pre = next;
next = tmp;
}
else {
if(w[next][0] < 0) t_res += -w[next][0];
pre = next;
next = tmp;
}
}
res = min(res, t_res);
printf("%d\n", res);
}
return 0;
}