最小生成树 最小树形图
/**************************** Kruskal算法 *****************************/ int father[maxn],n,m; int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void merge(int a,int b){ int fx,fy; fx=find(a); fy=find(b); if(fx!=fy) father[fx]=fy; } struct node { int from,to,val; bool select; }edge[maxe]; bool cmp(node a,node b) { if(a.val!=b.val) return a.val<b.val; if(a.from!=b.from) return a.from<b.from; return a.to<b.to; } int kruskal(int t) { int k=0; int i,x,y; int ans=0; for(i=1;i<=n;i++) { father[i]=i; } sort(edge,edge+m,cmp); for(i=0;i<m;i++) { if(k==n-1) break; if(edge[i].val<0) continue; if(i==t) continue; x=find(edge[i].from); y=find(edge[i].to); if(x!=y){ merge(x,y); k++; ans+=edge[i].val; edge[i].select=true; } } return ans; } void init() {memset(edge,0,sizeof(edge));}
模板题 POJ 3164 代码
/**************************** 最小树形图 zhuliu算法 先缩有向环 *****************************/ double zhuliu(int n,double map[maxn][maxn]) { bool visit[maxn]; bool flag[maxn];//缩点标记为ture,则该点已经被缩掉,否则依然存在 int pre[maxn]; double sum=0; int i,j,k; for(i=0;i<n;i++) { flag[i]=false; map[i][i]=INF; } pre[0]=0; while(true) { //求最短弧集合E0 for(i=1;i<n;i++) { if(flag[i]) continue; pre[i]=i; for(j=0;j<n;j++){ if(!flag[j]&&map[j][i]<map[pre[i]][i]) pre[i]=j; } if(pre[i]==i) return -1; } //检查E0 for(i=1;i<n;i++) { if(flag[i]) continue; //从当前点开始找环 for(j=0;j<n;j++) visit[j]=false; visit[0]=true; j=i; do { visit[j]=true; j=pre[j]; }while(!visit[j]); if(!j) continue; //没有找到环 //收缩G中的有向环 i=j; ///将整个环的权值保存,累计入原图的最小树形图 do { sum+=map[pre[j]][j]; j=pre[j]; }while(j!=i); j=i; //对与环上的点有关的边,修改边权 do { for(k=0;k<n;k++){ if(!flag[k]&&map[k][j]<INF&&k!=pre[j]) map[k][j]-=map[pre[j]][j]; } j=pre[j]; }while(j!=i); //缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i for(j=0;j<n;j++) { if(j==i) continue; for(k=pre[i];k!=i;k=pre[k]) { if(map[k][j]<map[i][j]) map[i][j]=map[k][j]; if(map[j][k]<map[j][i]) map[j][i]=map[j][k]; } } //标记环上其他的点为被缩掉 for(j=pre[i];j!=i;j=pre[j]) flag[j]=true; //当前环缩点结束,形成新的图G1,跳出继续求G1的最小树形图 break; } //如果所有的点都被检查切没有环存在,现在的环最短弧几何E0就是最小树形图, //累计入sum,算法结束 if(i==n) { for(i=1;i<n;i++) { if(!flag[i]) sum+=map[pre[i]][i]; } break; } } }