题目链接:
https://vijos.org/p/1427
题意:给文件夹之间的包含关系,0代表根目录。问从s文件夹到t文件夹,读取他们文件夹名的长度,并询问最少耗时。已知打开一个文件夹耗时问为该文件夹下子文件夹的数量。
思路:
最近公共祖先,话说状态真的好渣。
需要注意是求时间会求错,因为比如当s是t 的祖先时,是不需要打开s或打开t的。ie.需要在时间上做特殊判断。
源码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <climits>
#include <vector>
using namespace std;
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
typedef long long LL;
const int MAXN = 10000+5;
int fa[MAXN];
int len[MAXN],num[MAXN],tlen[MAXN];///记录增加后长度,子文件夹个数,原来长度
int vis[MAXN];///记录是否访问过
int lv[MAXN];///记录用时
char str[300];
int fi(int s,int t)
{
int temp = s;
while(temp != 0){
if(temp == t)
return 1;
temp = fa[temp];
}
temp = t;
while(temp != 0){
if(temp == s)
return -1;
temp = fa[temp];
}
return 0;
}
int main()
{
int n,s,t;
while(scanf("%d%d%d",&n,&s,&t) != EOF){
int le,ri;
memset(vis, 0, sizeof(vis));
memset(len, 0, sizeof(len));
memset(num, 0, sizeof(num));
for(int i=1; i<=n; i++){
fa[i] = i;
}
for(int i=0; i<n; i++){
scanf("%d%d%s",&le,&ri,str);
len[le] += strlen(str);
fa[le] = ri;
num[ri]++;
}
memcpy(tlen, len, sizeof(len));
memcpy(lv, num, sizeof(num));
int now = s;
for(int i=0; i<=n; i++)
lv[i] = num[i];
fa[0] = 0;
int f = 1;
int ans2 = 0;
while(now != 0){
int ff = fa[now];
vis[now] = 1;
// ans2++;
if(f)
f = 0;
else
lv[ff] += lv[now];
// printf("num[ff] = %d\n",num[ff]);
// printf("ff = %d,now = %d\n",ff,now);
len[ff] += len[now];
now = ff;
}
now = t;
// printf("second\n");
f = 1;
while(fa[now] != now && vis[now] == 0){
int ff = fa[now];
if(f)
f = 0;
else
lv[ff] += lv[now];
vis[now] = 1;
// printf("num[ff] = %d\n",num[ff]);
// printf("ff = %d,now = %d\n",ff,now);
len[ff] += len[now];
now = ff;
}
// for(int i=0; i<=n; i++)
// printf("%d ",lv[i]);
// printf("\n");
// printf("now = %d\n",now);
// printf("lv[now] = %d,ans2 = %d,num[now] = %d\n",lv[now],ans2,num[now]);
// printf("now = %d\n",now);
if(fi(s,t) == -1)
printf("%d\n%d\n",len[now],lv[now] - num[s]);
else if(fi(s,t) == 1)
printf("%d\n%d\n",len[now],lv[now] - num[t]);
else
printf("%d\n%d\n",len[now],lv[now]);
}
return 0;
}
/*
6 5 4
1 2 Lo
2 3 ra
3 0 .
4 2 bi
5 4 t
6 5 .COM
*/