İstənilən ağacın zirvəsindən dərinlik üzrə axtarış başladaq. çəkili üzünü nəzərdən keçirdək. Deyək ki, kök olan alt ağacda olan zirvələrin sayı -dir. Onda bir tərəfdəki ucluqda zirvə, digər tərəfdə isə n - c zirvə olur. üzü c \cdot (n - c) müxtəlif zirvə cütləri arasında olan yollara düşür. Beləliklə, üzünün bütün yolların cəmi uzunluğuna olan təsiri c \cdot (n - c) \cdot w-ya bərabərdir. Dərinlik üzrə axtarış vasitəsilə bütün üzülləri yoxlamaq və onların cəmi uzunluqlara olan təsirini toplamaq qalır.
Nümunə
Nümunələrdə verilmiş qraflar belə görünür:
Birinci nümunədə üzüllərin bütün yolların cəmi uzunluğuna olan təsirini nəzərdən keçirək.
Çəkisi olan üzü iki yola daxildir:
1 - 2;
2 - 1 - 3;
Onun cəmi uzunluğa olan təsiri 1 \cdot 2 \cdot 1 = 2-yə bərabərdir.
Çəkisi olan üzü iki yola daxildir:
1 - 3;
2 - 1 - 3;
Onun cəmi uzunluğa olan təsiri 2 \cdot 1 \cdot 3 = 6-yə bərabərdir.
Bütün yolların cəmi uzunluğu 2 + 6 = 8-ə bərabərdir.
İkinci nümunədə üzü çəkisi olanın bütün yolların cəmi uzunluğuna təsirini nəzərdən keçirək.
v = 2 kök olan alt ağacda zirvələrin sayı с = 4-dir (öz zirvəsi -i də daxil olmaqla). Onda üzünün digər tərəfində n - c = 6 - 4 = 2 zirvə var. Beləliklə, c * (n - c) = 4 * 2 = 8 müxtəlif yol var ki, onlar üzündən keçir. Doğrudan da, bu yolların hamısı zirvəsinin alt ağacında olmayan zirvələrdən ibarət olanlərdir. Beləliklə:
Çəkisi olan üzünün bütün yolların cəmi uzunluğuna təsiri belədir:
Alqoritmin həyata keçirilməsi
MOD dəyərini müəyyən edək.
#define MOD 1000000000Giriş çəkili qrafını qonşuluq siyahısına saxlayaq.
vector<vector<pair<int,int> > > g;Funksiya dfs -dən başlanan dərinlik üzrə axtarışı həyata keçirir və kökü olan alt ağacda zirvələrin sayını qaytarır (öz zirvəsi daxil olmaqla). Bu zirvələrin sayı dəyişənində saxlanılır. Əvvəlcə cnt = 1 olur, çünki alt ağac artıq özündə zirvəsini ehtiva edir.
int dfs(int v, int p = -1)
{
int cnt = 1;
for (auto edge : g[v])
{
int to = edge.first;
int w = edge.second;Çəkisi olan (v, to) üzünü nəzərə alaq. zirvəsinin kökü olduğu alt ağacda zirvələrin sayını hesablayırıq. Onda bir tərəfdə üzü zirvəsi var, digərində isə n - c zirvələri var. (v, to) üzü c \cdot (n - c) müxtəlif zirvə cütləri arasında olan yollara daxildir.
Beləliklə, (v, to) üzünün bütün yolların cəmi uzunluğuna olan təsiri belədir:
if (to != p)
{
int c = dfs(to, v);
res = (res + 1LL * c * (n - c) * w) % MOD;
cnt += c;
}
}
return cnt;
}Proqramın əsas hissəsi. Giriş çəkili qrafını qonşuluq siyahısına oxuyuruq.
scanf("%d", &n);
g.resize(n + 1);
for (i = 1; i < n; i++)
{
scanf("%d %d %d", &u, &v, &d);
g[u].push_back({v, d});
g[v].push_back({u, d});
}Dərinlik üzrə axtarışı zirvəsindən başlatmaq. Qraf zirvələri -dən -ə qədər nömrələnir.
dfs(1);Cavabı göstərmək.
printf("%lld\n",res);Java reallaşdırılması
import java.util.*;
import java.io.*;
class Edge
{
int to;
int weight;
public Edge(int to, int weight)
{
this.to = to;
this.weight = weight;
}
}
public class Main
{
static int MOD = 1000000000;
static ArrayList<Edge>[] g;
static int n, m;
static long res;
static int dfs(int v, int p)
{
int cnt = 1;
for(Edge edge : g[v])
{
int to = edge.to;
int w = edge.weight;
if (to != p)
{
int c = dfs(to, v);
res = (res + 1L * c * (n - c) * w) % MOD;
cnt += c;
}
}
return cnt;
}
public static void main(String[] args)
{
FastScanner con = new FastScanner(System.in);
n = con.nextInt();
g = new ArrayList[n+1]; // unchecked
for (int i = 0; i <= n; i++)
g[i] = new ArrayList<Edge>();
for (int i = 1; i < n; i++)
{
int u = con.nextInt();
int v = con.nextInt();
int d = con.nextInt();
g[u].add(new Edge(v,d));
g[v].add(new Edge(u,d));
}
dfs(1,-1);
System.out.println(res);
}
}
class FastScanner
{
BufferedReader br;
StringTokenizer st;
public FastScanner(InputStream inputStream)
{
br = new BufferedReader(new InputStreamReader(inputStream));
st = new StringTokenizer("");
}
public String next()
{
while (!st.hasMoreTokens())
{
try
{
st = new StringTokenizer(br.readLine());
} catch (Exception e)
{
return null;
}
}
return st.nextToken();
}
public int nextInt()
{
return Integer.parseInt(next());
}
}Python reallaşdırılması
MOD dəyərini müəyyən edək.
MOD = 1000000000Funksiya dfs -dən başlanan dərinlik üzrə axtarışı həyata keçirir və kökü olan alt ağacda zirvələrin sayını qaytarır (öz zirvəsi daxil olmaqla). Bu zirvələrin sayı dəyişənində saxlanılır. Əvvəlcə cnt = 1 olur, çünki alt ağac artıq özündə zirvəsini ehtiva edir.
def dfs(v, p = -1):
global res
cnt = 1
for to, w in g[v]:Çəkisi olan (v, to) üzünü nəzərə alaq. zirvəsinin kökü olduğu alt ağacda zirvələrin sayını hesablayırıq. Onda bir tərəfdə üzü zirvəsi var, digərində isə n - c zirvələri var. (v, to) üzü c \cdot (n - c) müxtəlif zirvə cütləri arasında olan yollara daxildir.
Beləliklə, (v, to) üzünün bütün yolların cəmi uzunluğuna olan təsiri belədir:
if to != p:
c = dfs(to, v)
res = (res + c * (n - c) * w) % MOD
cnt += c
return cntProqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
n = int(input())
g = [[] for _ in range(n + 1)]
res = 0
for _ in range(n - 1):
u, v, d = map(int, input().split())
g[u].append((v, d))
g[v].append((u, d))Dərinlik üzrə axtarışı zirvəsindən başlatmaq. Qraf zirvələri -dən -ə qədər nömrələnir.
dfs(1)Cavabı göstərmək.
print(res)