時間限制: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;
}