题目
一个武术高手,可以学T种武术,但他只想学第T个武术,学每个武术有需要花费的时间和前置武术条件(即要先学会前置的武术)。
求他学会第T个武术需要的最少时间。
题解思路
一开始想并查集什么的,没想太明白。
如果从图论想的话,这题就可以解决了。
如果正向建图的话,不容易得出答案的。因为起点难确定。
而如果反向建图的话,从T点出发往回跑,跑到每个武术的最基础武术点(即无需前置武术的那种)。并且每个点只跑一次。记录出来的就是答案。
帖大佬的一句话
我们反向跑的时候当这个点以及被学过了,那就没必要再跑一遍了。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100 ;
vector <int> head[N] ;
int a[N] ;
int vis[N] ;
void dfs(int p )
{
if ( p == 0 )
return ;
for (int i = 0 ; i < head[p].size() ; i++ )
{
int st = head[p][i] ;
if (!vis[st])
{
vis[st] = 1 ;
dfs(st) ;
}
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
for (int j = 1 ; j <= T ; j++ )
{
int s , n ;
cin >> s >> n ;
a[j] = s ;
for (int i = 1 ; i <= n ; i++ )
{
int t1 ;
cin >> t1 ;
head[j].push_back(t1) ;
}
}
dfs(T) ;
long long ans = a[T] ;
for (int i = 1 ; i < T ; i++ )
if (vis[i])
ans += a[i] ;
cout << ans << "\n" ;
return 0 ;
}