首页 > 其他分享 >最小树形图

最小树形图

时间:2023-03-27 09:47:01浏览次数:31  
标签:10 int namespace 最小 树形图 ri getchar

最小树形图

  1. 求最短弧集合 \(E\)
    找到每个 \(u\) 点的最小入边 \(in[u]\) ,如果存在非根节点没有入边,则一定不存在树形图
for(ri int i=1;i<=m;++i){
    if(e[i].u^e[i].v&&e[i].w<in[e[i].v]){
        in[e[i].v]=e[i].w,pre[e[i].v]=e[i].u;
    }
}
for(ri int i=1;i<=n;++i) if(i^rt&&!pre[i]) return -1;
  1. 判断集合 \(E\) 中有没有有向环,如果有转步骤 \(3\) ,否则转 \(4\)
    一定要记录 \(cnt\) 或开一个 \(bool\) 数组记录走过的边,不然可能疯狂走环;
cnt=in[rt]=0; 
		for(ri int i=1,v;i<=n;++i){
    as+=in[v=i];
    while(vs[v]^i&&!id[v]&&v^rt) vs[v]=i,v=pre[v];
    if(!id[v]&&v^rt){
        id[v]=++cnt,v=pre[v];
        while(!id[v]) id[v]=cnt,v=pre[v];
    }            
}
if(!cnt) break;
  1. 收缩点,把有向环收缩成一个点,并且对图重新构建,包括边权值的改变和点的处理,之后再转步骤 \(1\)
    对于环外指向环的边 \((u \to v, w)\) ,其边权变为 \(w-in[v]\)
for(ri int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
for(ri int i=1;i<=m;++i){
    if(id[e[i].u]^id[e[i].v]) e[i].w-=in[e[i].v];
    e[i].u=id[e[i].u],e[i].v=id[e[i].v];
} 
rt=id[rt],n=cnt;
  1. 展开收缩点,求得最小树形图
    如果不需要输出具体方案,直接返回 \(ans\) 即可
code
#include<bits/stdc++.h>
#define il inline
#define cs const
#define ri register
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(c^EOF&&!isdigit(c)) f|=(c==45),c=getchar();
        while(c^EOF&&isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
} using namespace Q;

cs int N=105,M=10004,inf=1<<30;
int in[N],pre[N],id[N],n,m,rt,vs[N];
struct qwq{int u,v,w;}e[M];

il int calc(){
    ri int as=0,cnt=0;
    while(1){
        for(ri int i=1;i<=n;++i) in[i]=inf,pre[i]=vs[i]=id[i]=0;
        for(ri int i=1;i<=m;++i){
            if(e[i].u^e[i].v&&e[i].w<in[e[i].v]){
                in[e[i].v]=e[i].w,pre[e[i].v]=e[i].u;
            }
        }
        for(ri int i=1;i<=n;++i) if(i^rt&&!pre[i]) return -1;
        cnt=in[rt]=0; 
		for(ri int i=1,v;i<=n;++i){
            as+=in[v=i];
            while(vs[v]^i&&!id[v]&&v^rt) vs[v]=i,v=pre[v];
            if(!id[v]&&v^rt){
                id[v]=++cnt,v=pre[v];
                while(!id[v]) id[v]=cnt,v=pre[v];
            }            
        }
        if(!cnt) break;
        for(ri int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
        for(ri int i=1;i<=m;++i){
            if(id[e[i].u]^id[e[i].v]) e[i].w-=in[e[i].v];
            e[i].u=id[e[i].u],e[i].v=id[e[i].v];
        } 
        rt=id[rt],n=cnt;
    }
    return as;
}

signed main(){
    n=rd(),m=rd(),rt=rd();
    for(ri int i=1;i<=m;++i){
        e[i].u=rd(),e[i].v=rd(),e[i].w=rd();
    }
    wt(calc());
    return 0;
}

标签:10,int,namespace,最小,树形图,ri,getchar
From: https://www.cnblogs.com/windymoon/p/17259265.html

相关文章

  • LeetCode 111.二叉树的最小深度
    1.题目给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。示例1:输入:root=[3,9,20,null,null......
  • docker镜像体积优化,拉取最小化jre镜像并构建nodejs环境
    镜像体积优化优化前构建镜像体积:1.2GB优化后构建镜像体积:621.63MB 优化思路,1.centos镜像体积太大,有几百MB,使用alpine版本体积更小。2.只需要jre即可,无需jdk。优化前......
  • [echarts] markLine 平均值,markPoint 最大值,最小值
    可以点这里,编辑代码option={title:{text:'TemperatureChangeintheComingWeek'},tooltip:{trigger:'axis'},legend:{},toolbox:{......
  • 做题记录 230324 // 最小生成树
    为什么擦眼睛会痛因为拭目痛いA.JungleRoadshttp://222.180.160.110:1024/contest/3452/problem/1纯最小生成树,比较坑的点是因为向POJ远程提交,所以没办法用万能头,......
  • 最小费用最大流( spfa )
     constintN=5005,M=1e5+100;#defineinf1e9intall=1,hd[N],go[M],w[M],nxt[M],cost[M];intS,T,n,m;intpre[N],mn[N],dis[N],vis[N],ans=0;void......
  • 【leetcode-数组】长度最小的子数组
    题目:给定一个含有 n 个正整数的数组和一个正整数 s,找出该数组中满足其和 ≥s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回0。示例: 输入:s=7......
  • P2764 最小路径覆盖问题
    求最少的路径数目覆盖DAG每个点(无点交集 #include<iostream>#include<algorithm>#include<queue>usingnamespacestd;constintN=500,M=5e5+5;constintinf......
  • 最小割树学习笔记
    前言最小割树(Gomory-HuTree)通过分治的思想,将图中的最小割关系建成一棵带权了树上问题。它的主要用途是求解全源最小割/最大流。前置知识:一种快速的最大流算法(Dinic/......
  • Leetcode209. 长度最小的子数组
    题目跳转链接滑动窗口解法代码随想录209.长度最小的子数组滑动窗口是一种基于双指针的算法,它可以用于解决一些数组/字符串的子元素问题,例如:找到最长的子数组、最小的子......
  • 最大公约数&最小公倍数
    最大公约数算法:要求a,b的最大公约数记作gcd(a,b),(假设a>b)我们就让a=a%b,如果a变为0那么b就为最大公约数,否则交换a,b继续执行上述操作直到求出最大公约数intgcd(......