最小树 次小树 模板
生活随笔
收集整理的這篇文章主要介紹了
最小树 次小树 模板
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
最小生成樹
?
? ? ?兩種算法,Kruskal 和 Prim ;
? ? ?Kruskal 是針對于稀疏圖的,因為他的復(fù)雜度是跟邊有關(guān)系的;
? ? ?先sort一便,然后用并查集加邊就行了,簡單沒什么說的.
?
? ? ?Prim 是針對于稠密圖的,這個算法自己很少用,就是每次都找到加入后邊最小的那個點
加進來就行了,前兩天hdu4756逼得我不得不看這個算法.
? ??
次小樹
? ?次小樹自己常用的也是兩種算法,不知道名字,可能算不上是什么算法吧
? ?先說一下思想吧,次小樹其實就是先找到一顆最小樹,然后刪除其中一條邊,找到一個最有
的可以連接兩個集合的邊就行了,更新到最后就是次小樹,其實也可以這樣,先跑一邊最小樹,
然后枚舉所有不是最小樹上的邊,想下,如果這條邊加在最小樹里肯定會產(chǎn)生環(huán),所以直接找
到環(huán)中最長的邊(該邊除外)減去就行了,這樣更新到最后也是次小樹,這就是第二種方法,第
一種方法中的找最小可以用樹形dp去優(yōu)化,如果暴力時間復(fù)雜度肯能會到o(n^3);
下面是模板
Kruskal
#include<algorithm>
#define MAX_EDGE 10000//邊的最大個數(shù)?
#define MAX_NODE 1000//點的最大個數(shù)
?
using namespace std;
typedef struct
{
? ?int a ,b;
? ?double dis;
}EDGE;
EDGE edge[MAX_EDGE]; //把邊存到這里?
int mer[MAX_EDGE];
?
bool camp(EDGE a ,EDGE b)
{
? ?return a.dis < b.dis;
}
int finds(int x)
{ ??
? ?return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
struct KRUSKAL
{
? ?double Kruskal (int edge_n ,int node_n)//邊和點的個數(shù)?
? ?{
? ? ? double ans; ??
? ? ? sort(edge + 1 ,edge + edge_n + 1 ,camp);
? ? ? for(int i = 0 ;i <= node_n ;i ++) mer[i] = i;
? ? ? ans = 0;
? ? ? for(int i = 1 ;i <= edge_n ;i ++)
? ? ? {
? ? ? ? ?int x = finds(edge[i].a);
? ? ? ? ?int y = finds(edge[i].b);
? ? ? ? ?if(x == y) continue;
? ? ? ? ?mer[x] = y;
? ? ? ? ?ans += edge[i].dis;
? ? ? }
? ? ? return ans;?
? ?}
}K;
? ?
Prim
struct PRIM //從0開始用?
{ ? ? ? ? ??
? ?double d[N];int vis[N]; ?
? ?bool mp[N][N]; ?//標記最小生成樹上的邊?
? ?double ans;//最小樹?
? ?int n;//點的個數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? 記得初始化 ? ?***
? ?double dis[N][N]; // 距離 ? ? ? ? ? ? ? ? ?記得初始化 ?*****
? ?
? ?
void prim()
{?
? ? for(int i=0;i<n;i++)
? ? { ?
? ? ? ? vis[i]=0; ?
? ? ? ? d[i]=dis[0][i]; ?
? ? } ?
? ? vis[0]=-1; ?
? ? ans=0; ?
? ? memset(mp,0,sizeof(mp)); ?
? ? for(int i=1;i<n;i++)
? ? { ?
? ? ? ? double Min= inf; ?
? ? ? ? int node=-1; ?
? ? ? ? for(int j=0;j<n;j++)
? ? ? ? { ?
? ? ? ? ? ? if(vis[j]!=-1 && d[j]<Min)
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? node=j; ?
? ? ? ? ? ? ? ? Min=d[j]; ?
? ? ? ? ? ? } ?
? ? ? ? } ?
??
? ? ? ? ans+=Min; ?//printf("%lf\n" ,ans); ?
? ? ? ? mp[vis[node]][node]=mp[node][vis[node]]=1; ?
? ? ? ? //add(vis[node],node); // 建樹 ?
? ? ? ? vis[node]=-1; ?
??
? ? ? ? for(int j=0;j<n;j++)
? ? ? ? { ?
? ? ? ? ? ? if(vis[j]!=-1 && d[j]>dis[node][j])
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? vis[j]=node; ?
? ? ? ? ? ? ? ? d[j]=dis[node][j]; ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? } ?
?}
}P;
剩下的那兩個 還沒有總結(jié)好模板,最近也正在學(xué),學(xué)完在總結(jié)補上吧..
? ? ?
? ??
?
? ? ?兩種算法,Kruskal 和 Prim ;
? ? ?Kruskal 是針對于稀疏圖的,因為他的復(fù)雜度是跟邊有關(guān)系的;
? ? ?先sort一便,然后用并查集加邊就行了,簡單沒什么說的.
?
? ? ?Prim 是針對于稠密圖的,這個算法自己很少用,就是每次都找到加入后邊最小的那個點
加進來就行了,前兩天hdu4756逼得我不得不看這個算法.
? ??
次小樹
? ?次小樹自己常用的也是兩種算法,不知道名字,可能算不上是什么算法吧
? ?先說一下思想吧,次小樹其實就是先找到一顆最小樹,然后刪除其中一條邊,找到一個最有
的可以連接兩個集合的邊就行了,更新到最后就是次小樹,其實也可以這樣,先跑一邊最小樹,
然后枚舉所有不是最小樹上的邊,想下,如果這條邊加在最小樹里肯定會產(chǎn)生環(huán),所以直接找
到環(huán)中最長的邊(該邊除外)減去就行了,這樣更新到最后也是次小樹,這就是第二種方法,第
一種方法中的找最小可以用樹形dp去優(yōu)化,如果暴力時間復(fù)雜度肯能會到o(n^3);
下面是模板
Kruskal
#include<algorithm>
#define MAX_EDGE 10000//邊的最大個數(shù)?
#define MAX_NODE 1000//點的最大個數(shù)
?
using namespace std;
typedef struct
{
? ?int a ,b;
? ?double dis;
}EDGE;
EDGE edge[MAX_EDGE]; //把邊存到這里?
int mer[MAX_EDGE];
?
bool camp(EDGE a ,EDGE b)
{
? ?return a.dis < b.dis;
}
int finds(int x)
{ ??
? ?return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
struct KRUSKAL
{
? ?double Kruskal (int edge_n ,int node_n)//邊和點的個數(shù)?
? ?{
? ? ? double ans; ??
? ? ? sort(edge + 1 ,edge + edge_n + 1 ,camp);
? ? ? for(int i = 0 ;i <= node_n ;i ++) mer[i] = i;
? ? ? ans = 0;
? ? ? for(int i = 1 ;i <= edge_n ;i ++)
? ? ? {
? ? ? ? ?int x = finds(edge[i].a);
? ? ? ? ?int y = finds(edge[i].b);
? ? ? ? ?if(x == y) continue;
? ? ? ? ?mer[x] = y;
? ? ? ? ?ans += edge[i].dis;
? ? ? }
? ? ? return ans;?
? ?}
}K;
? ?
Prim
struct PRIM //從0開始用?
{ ? ? ? ? ??
? ?double d[N];int vis[N]; ?
? ?bool mp[N][N]; ?//標記最小生成樹上的邊?
? ?double ans;//最小樹?
? ?int n;//點的個數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? 記得初始化 ? ?***
? ?double dis[N][N]; // 距離 ? ? ? ? ? ? ? ? ?記得初始化 ?*****
? ?
? ?
void prim()
{?
? ? for(int i=0;i<n;i++)
? ? { ?
? ? ? ? vis[i]=0; ?
? ? ? ? d[i]=dis[0][i]; ?
? ? } ?
? ? vis[0]=-1; ?
? ? ans=0; ?
? ? memset(mp,0,sizeof(mp)); ?
? ? for(int i=1;i<n;i++)
? ? { ?
? ? ? ? double Min= inf; ?
? ? ? ? int node=-1; ?
? ? ? ? for(int j=0;j<n;j++)
? ? ? ? { ?
? ? ? ? ? ? if(vis[j]!=-1 && d[j]<Min)
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? node=j; ?
? ? ? ? ? ? ? ? Min=d[j]; ?
? ? ? ? ? ? } ?
? ? ? ? } ?
??
? ? ? ? ans+=Min; ?//printf("%lf\n" ,ans); ?
? ? ? ? mp[vis[node]][node]=mp[node][vis[node]]=1; ?
? ? ? ? //add(vis[node],node); // 建樹 ?
? ? ? ? vis[node]=-1; ?
??
? ? ? ? for(int j=0;j<n;j++)
? ? ? ? { ?
? ? ? ? ? ? if(vis[j]!=-1 && d[j]>dis[node][j])
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? vis[j]=node; ?
? ? ? ? ? ? ? ? d[j]=dis[node][j]; ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? } ?
?}
}P;
剩下的那兩個 還沒有總結(jié)好模板,最近也正在學(xué),學(xué)完在總結(jié)補上吧..
? ? ?
? ??
總結(jié)
以上是生活随笔為你收集整理的最小树 次小树 模板的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu4081 最小树+DFS或者次小树
- 下一篇: hdu4126(MST + 树形dp