1. 程式人生 > 其它 >P6111 [USACO18JAN]MooTube S 題解

P6111 [USACO18JAN]MooTube S 題解

思路

把建出來的樹進行 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\) 的邊。對於每次 DFS,處理到那個視訊的最小相關性(使用類似處理最短路的方法)。最後繼續 DFS 另一個可以到的視訊。

如果這個視訊可以到達(即沒有走過相關性小於 \(k\) 的邊),就把計數器加 \(1\)

AC code

記錄

各部分已經分開給出。