P6111 [USACO18JAN]MooTube S 題解
阿新 • • 發佈:2022-01-26
思路
把建出來的樹進行 DFS,用類似最短路的方法跑出一個視訊到每個視訊的相關性(下文中用“單源相關性”描述)。為了防止多次跑同一個視訊的
“單源相關性”,可以使用一個二維陣列記錄,第二次詢問到這個視訊時可以直接讀取。
程式碼
2.1 建樹
for(int i=1;i<=n-1;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
p[x].push_back(make_pair(y,z));
p[y].push_back(make_pair(x,z));
}
使用鄰接表建樹。因為樹是一種特殊的無向圖,所以要建無向邊。
2.2 詢問主體結構
memset(d,0x3f,sizeof(d));
for(int i=1;i<=qu;i++){
memset(vis,0,sizeof(vis));
int k,v;
scanf("%d%d",&k,&v);
vis[v]=true;
dfs(v,v);
printf("%d\n",cnt);
}
因為每次都取最小值,要把 \(d\) 陣列初始化為 \(inf\)(注意 \(inf\) 至少要比所有邊的相關性大,我這裡選擇的是0x3f
)。
每次開始之前要把用於 DFS 的 \(vis\) 陣列清空為 \(false\) 並把 \(vis_v\) 設為 \(true\)
2.3 DFS 結構
void dfs(int x,int y,int k){
for(int i=0;i<p[y].size();i++){
if(!vis[p[y][i].first]&&p[y][i].second>=k){
cnt++;
vis[p[y][i].first]=true;
d[x][p[y][i].first]=min(d[x][p[y][i].first],min(d[x][y],p[y][i].second));
dfs(x,p[y][i].first,k);
}
}
}
每次 DFS 一個沒有到過的視訊,為了保證我們到達的視訊相關性至少為 \(k\)
如果這個視訊可以到達(即沒有走過相關性小於 \(k\) 的邊),就把計數器加 \(1\)。
AC code
各部分已經分開給出。