CodeForces 618D Hamiltonian Spanning Tree

题意:要把所有的节点都访问一次,并且不能重复访问,有两种方式访问,一种是根据树上的路径

走和当前节点连接的下一个节点cost x, 或者可以不走树上边,直接跳到不与当前节点连接的节点,cost y

分析:

别被树吓着!

一定会走n-1条路,那么就是有一些走树上的边,有一些不走。

如果树上的路径cost更大(x >= y),那么尽可能的不走树上的路径,那么根据尝试可以找到规律

如果有一个节点是所有节点的父节点,也就是说这个节点的度为n-1,那么只会走一个x其他都是y

如果没有这个节点,一定可以全部走y

另一种情况如果(x < y),那么也就是说要尽可能的多走树上的边,我们知道一个节点只能访问一次,也就是说

一个节点最多只能连两条边出去,然后dfs搜索,找到最多可以走多少条,每个节点的度数如果不被剪完就可以继续连,

剩下的只能走y。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <queue>
  5 #include <vector>
  6 #include <algorithm>
  7 #include <stack>
  8 #include <set>
  9 #include <map>
 10 #include <math.h>
 11 #define pb push_back
 12 #define CLR(a) memset(a, 0, sizeof(a));
 13 #define MEM(a, b) memset(a, b, sizeof(a));
 14 #define fi first
 15 #define se second
 16 
 17 using namespace std;
 18 
 19 typedef long long ll;
 20 
 21 const int MAXN = 200007;
 22 const int MAXV = 207;
 23 const int MAXE = 207;
 24 const int INF = 0x3f3f3f3f;
 25 ll x, y, n;
 26 struct Edge
 27 {
 28     int to, next;
 29     Edge () {}
 30     Edge(int to, int next) : to(to), next(next) {}
 31 }edge[MAXN << 1];
 32 int num;
 33 int head[MAXN];
 34 void Add(int from, int to)
 35 {
 36     edge[num] = Edge(to, head[from]);
 37     head[from] = num++;
 38 }
 39 int deg[MAXN];
 40 ll ans = 0;
 41 ll len = 0;
 42 int cnt = 0;
 43 bool dfs(int crt, int fa)
 44 {
 45     int rem = 2;
 46     for (int t = head[crt]; t != -1; t = edge[t].next)
 47     {
 48         Edge e = edge[t];
 49         int v = e.to;
 50         if (v == fa) continue;
 51         if (dfs(v, crt) && rem > 0)
 52         {
 53             len++; rem--;
 54         }
 55     }
 56     return rem > 0;
 57 }
 58 
 59 int main()
 60 {
 61     //freopen("in.txt", "r", stdin);
 62     while (~scanf("%lld%lld%lld", &n, &x, &y))
 63     {
 64         MEM(head, -1);
 65         MEM(edge, -1);
 66         CLR(deg);
 67         num = 0;
 68         len = 0;
 69         for (int i = 0; i < n-1; i++)
 70         {
 71             int u, v;
 72             scanf("%d%d", &u, &v);
 73             Add(u, v);
 74             Add(v, u);
 75             deg[u]++;
 76             deg[v]++;
 77         }
 78         bool done = false;
 79         if (x >= y)
 80         {
 81             for (int i = 1; i <= n; i++)
 82             {
 83                 if (deg[i] == n-1)
 84                 {
 85                     ans = y*(n-2)+x;
 86                     printf("%lld
", ans);
 87                     done = true;
 88                     break;
 89                 }
 90             }
 91             if (done) continue;
 92             ans = (n-1)*y;
 93             printf("%lld
", ans);
 94             continue;
 95         }
 96         dfs(1, 0); ans = len*x + (n-1-len)*y;
 97         printf("%lld
", ans);
 98     }
 99     return 0;
100 }
原文地址:https://www.cnblogs.com/oscar-cnblogs/p/7615582.html