• 最小树形图模板


    朱流算法,模板里的图存储方法是结构体

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 #include<cctype>
     9 #include<stack>
    10 #define pn putchar('
    ')
    11 #define pd putchar(' ')
    12 #define num ch-'0'
    13 #define pb push_back
    14 #define mp make_pair
    15 #define fi first
    16 #define se second
    17 #define reint register int
    18 #define fre1 freopen("1.txt","r",stdin);
    19 #define fre2 freopen("2.txt","w",stdout)
    20 using namespace std;
    21 template <typename T>
    22 void read(T &res)
    23 {
    24     char ch;bool flag=false;
    25     while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
    26     for(res=num;isdigit(ch=getchar());res=res*10+num);
    27     flag&&(res=-res);
    28 }
    29 template <typename T>
    30 void write(T x)
    31 {
    32     if(x<0)putchar('-'),x=-x;
    33     if(x>9)write(x/10);
    34     putchar(x%10+'0');
    35 }
    36 typedef long long ll;
    37 const int INF=0x7fffffff;
    38 const int inf=0x3f3f3f3f;
    39 const int mod=1000000007;
    40 const int N=110;
    41 const int M=10010;
    42 struct node {
    43     int u,v,w;
    44 }e[M];
    45 int n,m,r;
    46 int pre[N],id[N],f[N],minn[N];
    47 ///f[]:类似并查集,用于缩点
    48 ///id[u]:表示u在第id[u]个环中
    49 ///pre[v]:表示入度为v的最小边权对应的u
    50 ///minn[v]:表示入度为v的最小边权
    51 int edmonds() {
    52     ll ans=0;
    53     int cnt=0;
    54     while(true) {
    55         for(int i=1;i<=n;i++)           ///重新找缩点后的最小树形图
    56             id[i]=f[i]=0,minn[i]=inf;
    57         for(int i=1;i<=m;i++)
    58             if(e[i].u!=e[i].v&&minn[e[i].v]>e[i].w)
    59             ///不是自环,且边权小于之前选定的
    60                 minn[e[i].v]=e[i].w,pre[e[i].v]=e[i].u;
    61         int u=minn[r]=0;
    62         for(int i=1;i<=n;i++) {
    63             if(minn[i]==inf)
    64             ///即该点入度为0,没连接到,不存在最小树形图
    65                 return -1;
    66             ans+=minn[i];
    67             for(u=i;u!=r&&f[u]!=i&&!id[u];u=pre[u]) f[u]=i;
    68             if(u!=r&&!id[u]) {  ///存在环,进行缩点
    69                 id[u]=++cnt;
    70                 for(int v=pre[u];u!=v;v=pre[v]) id[v]=cnt;
    71             }
    72         }
    73         if(!cnt) return ans;    ///不存在环,返回答案
    74         for(int i=1;i<=n;i++)
    75             if(!id[i]) id[i]=++cnt;  ///i结点不在树中,给它安排一个
    76         for(int i=1;i<=m;i++) {
    77             int temp=minn[e[i].v];
    78             if((e[i].u=id[e[i].u])^(e[i].v=id[e[i].v]))
    79             ///检测是否在同一个环中
    80                 e[i].w-=temp;
    81                 ///u=e[i].u, v=e[i].v;
    82                 ///设u',v'为收缩后的点;
    83                 ///当v为收缩点时,e<u,v'>=e<u,v>-minn[v];
    84                 ///当u为收缩点时,在之前e<u,v>已经累加进入ans
    85                 ///由每个点的入度只为1可得,e<u',v>=0;
    86         }
    87         n=cnt;r=id[r];cnt=0;
    88     }
    89 }
    90 int main()
    91 {
    92     read(n),read(m),read(r);
    93     for(int i=1;i<=m;i++)
    94         read(e[i].u),read(e[i].v),read(e[i].w);
    95     write(edmonds());pn;
    96     return 0;
    97 }
  • 相关阅读:
    基于Linux OpenJDK Debian的发行版的JAVA_HOME环境变量的正确目标是什么?
    redhat linux卸载默认的openjdk与安装sun的jdk
    更换介质:请把标有…… DVD 的盘片插入驱动器“/media/cdrom/”再按回车键“ 解决方法
    mysql 导出表结构和表数据 mysqldump用法
    转怎么让VI支持中文显示
    debian 更换sh的默认链接为bash
    基于percona-monitoring-plugins实现Zabbix的MySQL多端口自动发现监控
    elasticsearch中client.transport.sniff的使用方法和注意事项
    网络大数据分析 -- 使用 ElasticSearch + LogStash + Kibana 来可视化网络流量
    Parsing Netflow using Kibana via Logstash to ElasticSearch
  • 原文地址:https://www.cnblogs.com/wuliking/p/10988577.html
Copyright © 2020-2023  润新知