fzu 2038 Another Postman Problem 递归
2016-10-16 14:01
429 查看
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
Sample Output
思路:
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;
}
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;
}
相关文章推荐
- fzu 2038 Another Postman Problem(递归求解)
- FZU - 2038 Another Postman Problem
- fzu 2038 Another Postman Problem(dfs)
- fzu2038 Another Postman Problem
- FZU 2038 Another Postman Problem【思维】
- fzu 1753 Another Easy Problem
- Another Easy Problem FZU - 1753唯一分解定理
- FZU1753 Another Easy Problem【组合数】
- FZU 1753 Another Easy Problem 解题报告(素因子统计)
- FZU_1753 Another Easy Problem
- fzu 1753 Another Easy Problem
- fzu-1753 Another Easy Problem-快速求N!中有多少个p
- fzu-1753 Another Easy Problem-高速求N!多少个月p
- 【解题报告】fzu 1753 Another Easy Problem - 求150个组合数的最大公约数
- fzu 1753 Another Easy Problem(n!的素因子分解)
- Another Postman Problem (邻接表+DFS)
- FZU 1753:Another Easy Problem _素因子分解
- FZU 1753-Another Easy Problem(求多个组合数的最大公约数)
- fzu 2038图的遍历,递归求解
- fzu1753 Another Easy Problem