• (最小树形图)POJ 3164


    题意:

    给定一个有向图,求以某个给定顶点为根的有向生成树(也就是说沿着这N-1条有向边可以从根走到任一点),使权和最小。

    分析:

    这题直接朱刘算法,虽然看起来很偏门,但是还是要学一下。算法过程很多博客都有了,这里就不赘述了。

    不过貌似CSU1828是朱刘算法+AC自动机,可以刷一刷。

    代码:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 #include <vector>
      6 #include <cmath>
      7 
      8 using namespace std;
      9 
     10 const int inf = 0x3f3f3f3f;
     11 const int maxn = 110;
     12 
     13 
     14 int n, m;
     15 double x[maxn], y[maxn];
     16 
     17 double dis(double x1, double y1, double x2, double y2) {
     18     return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
     19 }
     20 
     21 struct Edge {
     22     int u, v;
     23     double c;
     24 };
     25 
     26 Edge edge[10010];
     27 
     28 double in[maxn];
     29 int pre[maxn];
     30 int id[maxn];
     31 int vis[maxn];
     32 
     33 double MTV(int root) {
     34     double ans = 0;
     35     while(1) {
     36         for(int i = 0; i < n; i++) in[i] = inf;
     37         for(int i = 0; i < m; i++) {
     38             int u = edge[i].u;
     39             int v = edge[i].v;
     40             if(edge[i].c < in[v] && u != v) {
     41                 in[v] = edge[i].c;
     42                 pre[v] = u;
     43             }
     44         }
     45 
     46         for(int i = 0; i < n; i++) {
     47             if(i == root) continue;
     48             if(in[i] == inf) return -1;
     49         }
     50 
     51         int cnt = 0;
     52         memset(id, -1, sizeof(id));
     53         memset(vis, -1, sizeof(vis));
     54         in[root] = 0;
     55         for(int i = 0; i < n; i++) {
     56             ans += in[i];
     57             int v = i;
     58             while(vis[v] != i && id[v] == -1 && v != root) {
     59                 vis[v] = i;
     60                 v = pre[v];
     61             }
     62             if(v != root && id[v] == -1) {
     63                 for(int u = pre[v]; u != v; u = pre[u]) {
     64                     id[u] = cnt;
     65                 }
     66                 id[v] = cnt++;
     67             }
     68         }
     69         if(cnt == 0) break;
     70 
     71         for(int i = 0; i < n; i++) {
     72             if(id[i] == -1) id[i] = cnt++;
     73         }
     74 
     75         for(int i = 0; i < m; i++) {
     76             int v = edge[i].v;
     77             edge[i].v = id[edge[i].v];
     78             edge[i].u = id[edge[i].u];
     79             if(edge[i].u != edge[i].v) {
     80                 edge[i].c -= in[v];
     81             }
     82         }
     83         n = cnt;
     84         root = id[root];
     85     }
     86     return ans;
     87 }
     88 
     89 
     90 
     91 int main() {
     92     while(~scanf("%d%d", &n, &m)) {
     93         for(int i = 0; i < n; i++) {
     94             scanf("%lf%lf", &x[i], &y[i]);
     95         }
     96         for(int i = 0; i < m; i++) {
     97             int u, v;
     98             scanf("%d%d", &u, &v);
     99             u--, v--;
    100             if(u == v)edge[i] = Edge{u, v, inf};
    101             else edge[i] = Edge{u, v, dis(x[u], y[u], x[v], y[v])};
    102         }
    103         double ans = MTV(0);
    104         if(ans < 0)puts("poor snoopy");
    105         else printf("%.2f
    ", ans);
    106     }
    107 
    108     return 0;
    109 
    110 }
  • 相关阅读:
    算法-动态规划 Dynamic Programming--从菜鸟到老鸟
    DTW动态时间规整
    安装splash
    安装 Tesserocr (填坑)
    pip3 install tesserocr安装失败(已解决)
    从头到尾彻底理解傅里叶变换算法
    ruby之——安装gem提示:Please update your PATH to include build tools or download the DevKit
    关于0x80000000为什么等于-2147483648和负数在内存上储存的问题
    html5 canvas
    html5 视频和音频
  • 原文地址:https://www.cnblogs.com/tak-fate/p/6882552.html
Copyright © 2020-2023  润新知