//最小生成树模板
/* kruskal算法,把所有的边从小到大排序,接下来从小到大考查每条边(u,v);
1.u和v在同一个连通分量中,那么加入(u,v)后会形成环,因此不能选择。
2.如果u和v在不同的联通分量中,那么加入(u,v)一定是最优的。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int fat[102];//存放父节点
struct Lu
{
int u,v,w;
};
bool cmp(Lu x,Lu y) {return x.w<y.w;}//排序函数
int find(int x) {return fat[x]==x?x:find(fat[x]);}//并查集,找根节点
int main()
{
for(int i=0;i<=100;i++)//初始化并查集
fat[i]=i;
sort(L,L+k,cmp);//给边排序
for(int i=0;i<k;i++)
{
int x=find(L[i].u),y=find(L[i].v);
if(x!=y) //不在同一个并查集,合并
{
fat[y]=x;
sum+=L[i].w;//权值加
}
}
return 0;
}
************************************************************************
/* prim算法,任选一点s放到S集合中,从不在S集合中的点中选出一个点j使得其与S中的某点i的距离最短,
则(i,j)就是生成树的一条边,加入S中。继续按照上面找。数据量较大时用prim方便。
*/
//prim 模板。这题数据太大用cruscal会超时。
#include<iostream>
#include<cstdio>
#include<cstring>
int dis[502],map[502][502],mark[502];
const int MAX=10000007;
int prim(int n)
{
for(int i=1;i<=n;i++) //初始化每个点到生成树中点的距离
{
dis[i]=map[1][i];
mark[i]=0;
}
mark[1]=1; //1这个点加入生成树中。
int sum=0;
for(int i=1;i<n;i++) //枚举n-1条边
{
int sta=-1,Min=MAX;
for(int j=1;j<=n;j++) //找不在生成树中的点中距离生成树中的点长度最小的
{
if(!mark[j]&&dis[j]<Min)
{
Min=dis[j];
sta=j;
}
}
if(sta==-1) return -1; //没找到可以可以联通的路
mark[sta]=1; //新找到的点加入生成树
sum+=Min;
for(int j=1;j<=n;j++) //更新树外的点到树中的点的距离
{
if(!mark[j]&&dis[j]>map[sta][j])
dis[j]=map[sta][j];
}
}
return sum;
}
int main()
{
return 0;
}
/**********次小生成树*********************************/
//次小生成树最多有一条边与最小生成树不同,求出最小生成树后,枚举不在最小生成树中的边u-v,
//加入这条边会形成环,因此再去掉最小生成树中u-v路径中的权值最大的边。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int t,n,m,mp[110][110],vis[110],maxl[110][110],dis[110],pre[110],used[110][110];
int Prim(){
memset(maxl,0,sizeof(maxl));
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++){
dis[i]=mp[1][i];
vis[i]=0;pre[i]=1;
}
vis[1]=1;
int ans=0;
for(int i=1;i<n;i++){
int minl=inf,sta=-1;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<minl){
minl=dis[j];
sta=j;
}
}
if(sta==-1) return -1;
vis[sta]=1;
used[sta][pre[sta]]=used[pre[sta]][sta]=1;
ans+=minl;
for(int j=1;j<=n;j++){
if(vis[j]&&j!=sta)
maxl[sta][j]=maxl[j][sta]=max(maxl[pre[sta]][j],dis[sta]);
else if(!vis[j]&&dis[j]>mp[sta][j]){
dis[j]=mp[sta][j];
pre[j]=sta;
}
}
}
return ans;
}
int Smst(int ans){
int tmp=inf;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(used[i][j]||mp[i][j]==inf) continue;
tmp=min(tmp,ans+mp[i][j]-maxl[i][j]);
}
}
if(tmp==inf) return -1;
return tmp;
}
int main()
{
return 0;
}