Template-Minimal Tree Diagram (Zhu Liu Algorithm)

A collated collection of algorithm templates: ACM templates


The smallest tree graph of a directed graph given a root

Given a graph with n nodes and m directed edges. Try to find a minimum tree graph rooted at node r, and output the sum of the weights of each edge of the minimum tree graph. If there is no
minimum tree graph rooted at r , output −1.

#include<bits/stdc++.h>
using namespace std;
const int N=106,M=10006,inf=2e8;
int n,m,rt,t,cnt=0,id[N],pre[N],ine[N],vis[N];
struct line{
    
    int x,y,c;}q[M];
inline int read(){
    
    
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){
    
    if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
int zhuliu(){
    
    
    int ans=0;
    while(true){
    
    
         cnt=0;
         for(int i=1;i<=n;++i) ine[i]=inf,vis[i]=0,id[i]=0;//预处理
         for(int i=1;i<=m;++i) if(q[i].x!=q[i].y&&ine[q[i].y]>q[i].c) ine[q[i].y]=q[i].c,pre[q[i].y]=q[i].x;//每个点的最短边
         for(int i=1;i<=n;++i) if(i!=rt&&ine[i]==inf) return -1;//有点无最短边
         for(int i=1;i<=n;++i){
    
    
             if(i==rt) continue;
             ans+=ine[i],t=i;
             while(vis[t]!=i&&!id[t]&&t!=rt) vis[t]=i,t=pre[t];
             //能走到环的点或者换上的点停下
             if(!id[t]&&t!=rt){
    
    
                id[t]=++cnt; //将环上的点标记为新的环
                for(int o=pre[t];o!=t;o=pre[o]) id[o]=cnt;
             }
         }//找环
         if(!cnt) break;//无环结束
         for(int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
         for(int i=1;i<=m;++i){
    
    
             t=q[i].y,q[i].x=id[q[i].x],q[i].y=id[q[i].y];
             if(q[i].x!=q[i].y) q[i].c-=ine[t];
         }
         n=cnt,rt=id[rt];
         //去旧图,换新图
    }
    return ans;
}
int main(){
    
    
    n=read(),m=read(),rt=read();
    for(int i=1;i<=m;++i) q[i].x=read(),q[i].y=read(),q[i].c=read();
    printf("%d\n",zl());
    return 0;
} 

Dendrogram for a given root

Find a tree graph with no definite root: create a super root r and use it as the root to run the algorithm. Just connect r to each point of the original graph with an edge whose weight is greater than the weight of all edges in the original graph, and select these The edge is definitely not worthwhile, so only one will be chosen.

The method of judging no solution

Unsolvable tricks: enumerate each point i from small to large, add edges (i, (i + 1)% n + 1, + ∞) (i,(i+1)\%n+ 1,+\infty)(i,(i+1)%n+1,+ ) , so if you finally get the answer+ ∞ +\infty+ , then there is no solution.

Guess you like

Origin blog.csdn.net/weixin_45697774/article/details/108568123