1. 程式人生 > 其它 >最小生成樹和最小樹形圖

最小生成樹和最小樹形圖

最小生成樹 是在無向圖中 是把所有點連線的最小邊值;

pri 演算法:

貪心的思想,每次選擇最近的點。去更新

在更新那個點的時候,記錄一下那個最小的邊

struct cmp{
    bool operator ()(const int &a,const int &b)const
    {
        return dis[a]>dis[b];
    }
};
priority_queue <int,vector<int>,cmp> q;
int flag[M],minn[M];
int ans;

void bfs()
{
    memset(dis,
0x3f,sizeof(dis)); dis[t]=0; q.push(t);int a=t; while(!q.empty()) { while(!q.empty()) { a=q.top(); if(flag[a]) q.pop(); else break; } if(flag[a]) break; flag[a]=1; ans+=minn[a]; for(ri i=0;i<p[a].size();i++) {
if(flag[p[a][i].d]) continue; if(dis[p[a][i].d]>dis[a]+p[a][i].val) dis[p[a][i].d]=dis[a]+p[a][i].val,q.push(p[a][i].d),minn[p[a][i].d]=p[a][i].val; } } }
View Code

不能用prm 演算法解決 最小樹形圖

最小樹形圖 是有向圖的最小生成樹

演算法 zhuliu

思想: 從入度入手+縮點的思想;

void zl()
{
    
while(1){ for(ri i=1;i<=n;i++) dis[i]=inf; for(ri i=1;i<=m;i++) { int u,v; u=p[i].u,v=p[i].v; if(v!=u&&dis[v]>p[i].val){ pre[v]=u; dis[v]=p[i].val; } } for(ri i=1;i<=n;i++) { if(dis[i]==inf&&i!=root) /// { printf("-1"); exit(0); } } int cnt=0; for(ri i=1;i<=n;i++) vis[i]=0,id[i]=0; for(ri i=1;i<=n;i++) { if(i==root) continue; ans+=dis[i]; int v=i; while(vis[v]!=i&&!id[v]&&v!=root) /// 找迴圈 { vis[v]=i; v=pre[v]; } if(!id[v]&&v!=root) /// 很 妙 妙 妙 { id[v]=++cnt; for(int u=pre[v];u!=v;u=pre[u]) { id[u]=cnt; } } } if(!cnt) { printf("%d",ans); exit(0); } for(ri i=1;i<=n;i++) { if(!id[i]) id[i]=++cnt; } for(ri i=1;i<=m;i++) { int v=p[i].v, u=p[i].u; //////// 新編號 p[i].v=id[v]; p[i].u=id[u]; if(id[u]!=id[v]) { p[i].val-=dis[v]; } } n=cnt; root = id[root]; } }
View Code