题意:
就是给你一个图,然后龙龙刚开始在某个root点,现在给你m个外卖要送,每次给你一个新的外卖点,问你龙龙送完当前这些外卖最少要走多少距离(送完最后一个外卖停在这即可,不用回到初始点)。
思考:
害,感觉这场时间太紧了。其实刚看到这题我就感觉和我之前做过的那道巨木之森。那题就是要从一个点走完所有点,画图发现,每个点的深度都要走两次,只有最后一个要走的点的深度走一次。最后减去深度最大的就行了。然后当时想到之后,这题每次走完又不回到快递站,那怎么办,然后就想不出了,就乱搞了个floyd和全排列走的方案数,后来写了个lca也没调对。反正还有一点就是误导我了,我总想着走的顺序会影响答案,如果在同一条路线上确实会影响,但是不同路径之间是不影响的,之后最后走的点会影响一下,所以啊要画画图模拟模拟。
其实这题就也是每个点走的距离也需要是两次,但是每个新点走的距离仅仅是之前没走过的哪些点,然后答案就是再减去最大的深度。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define db double
#define int long long
#define PII pair<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod = 1e9+7,inf = 1e18;
const int N = 2e5+10,M = 2010;
int T,n,m,k;
int va[N];
int acc[N],root;
int dep[N];
int vis[N];
vector<int > e[N];
void dfs(int now,int p)
{
dep[now] = dep[p]+1;
for(auto spot:e[now])
{
if(spot==p) continue;
dfs(spot,now);
}
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>acc[i];
if(acc[i]==-1) root = i;
else e[acc[i]].pb(i);
}
dfs(root,0);
int ans = 0,maxn = 0;
while(m--)
{
int x;
cin>>x;
int sum = 0;
maxn = max(maxn,dep[x]);
while(x!=root&&!vis[x])
{
sum++;
vis[x] = 1;
x = acc[x];
}
ans += 2*sum;
cout<<ans-maxn+1;
if(m) cout<<"\n";
}
return 0;
}
总结:
害,还是自己太菜了,总想联想以前的思路,但是对不上又不去思考了。这也是我一直讨厌做重复题的一个原因吧,下意识的不愿意去思考了。就像这次昆明,那个二分01分数规划,感觉就是这样的,实际上就是个贪心而已。如果我没做过类似的题目,也许那个贪心就想到了,当时就是陷进去了。多多思考吧,积累经验。