fzu 2038 Another Postman Problem 遞歸

Description

Chinese Postman Problem is a very famous hard problem in graph theory. The problem is to find a shortest closed path or circuit that visits every edge of a (connected) undirected graph. When the graph has an Eulerian Circuit (a closed walk that covers every edge once), that circuit is an optimal solution.

This problem is another version of Postman Problem. Assume there are n towns and n-1 roads, and there is a unique path between every pair of towns. There are n-1 postmen in every town, and each postman in one town regularly sends mails to one of the other n-1 towns respectively. Now, given the length of each road, you are asked to calculate the total length that all the postmen need to travel in order to send out the mails.

For example, there are six towns in the following picture. The 30 postmen should totally travel 56. The postmen in town 0 should travel 1, 2, 2, 2, 3 respectively, the postmen in town 1 should travel 1, 1, 1, 1, 2 respectively, the postmen in town 2 should travel 1, 1, 2, 2, 2 respectively, the postmen in town 3 should travel 1, 2, 3, 3, 3 respectively, the postmen in town 4 should travel 1, 2, 2, 2, 3 respectively, and the postmen in town 5 should travel 1, 2, 2, 2, 3 respectively. So the total distance is 56.

Input

The first line of the input contains an integer T(T≤20), indicating the number of test cases. Each case begins with one integer n(n≤100,000), the number of towns. In one case, each of the following n-1 lines describes the length of path between pair a and b, with the format a, b, c(1≤c≤1000), indicating that town a and town b are directly connected by a road of length c. Note that all the n towns are numbered from 0 to n-1.

Output

For each test case, print a line containing the test case number (beginning with 1) and the total sum of the length that all postmen should travel.

Sample Input

1
6
0 1 1
1 2 1
2 3 1
1 4 1
1 5 1

Sample Output

Case 1: 56

思路:

n很大,常規方法會TLE。

可以看出,每條路經過次等於一邊的定點數乘另一邊的頂點數。

用遞歸來求兩邊頂點數

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

typedef long long LL;
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int t, n;

struct Node {
    int next, val;
    LL cnt;
    Node(int a, int b) {
        next = a;
        val = b;
        cnt = 0;
    }
};

vector<Node> G[MAXN];
bool vis[MAXN];

int DFS(int v) {
    vis[v] = true;
    int r = 0;
    for (int i = 0; i < G[v].size(); ++i) {
        int& u = G[v][i].next;
        if (vis[u]) continue;
        int temp = DFS(u);
        G[v][i].cnt = (LL)(n - temp) * temp;
        r += temp;
    }
    return ++r;
}

LL Solve() {
    memset(vis, 0, sizeof(vis));
    DFS(0);
    LL ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < G[i].size(); ++j) {
            ans += LL(G[i][j].cnt * G[i][j].val);
        }
    }
    return ans << 1;
}

int main() {
#ifdef NIGHT_13
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d", &t);
    int cas = 0;
    while (t--) {
        scanf("%d", &n);

        for (int i = 0; i < n; ++i) {
            G[i].clear();
        }

        for (int i = 1, a, b, c; i < n; ++i) {
            scanf("%d%d%d", &a, &b, &c);
            G[a].push_back(Node(b, c));
            G[b].push_back(Node(a, c));
        }
        printf("Case %d: %I64d\n", ++cas, Solve());
    }
    return 0;
}




發佈了96 篇原創文章 · 獲贊 8 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章