最小树形图

来源:互联网 发布:gre gmat 知乎 编辑:程序博客网 时间:2024/06/18 04:13
int ZLEdmonds(int n,int map[maxn][maxn]){    bool visited[maxn],flag[[maxn];    int pre[maxn];    int sum=0,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++){   //pre[i]保存终点为i的最短弧的起点。                     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++)                     visited[j]=false;                visited[0]=true;                                j=i;                do{                    visited[j]=true;                    j=pre[j];                }while( !visited[j]);                 if( !j) continue; //没有找到环。                                 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]&&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++){                                                    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];                      }                }                //标记环上其他的点为被缩掉  下次再找Ei时不参与                 for( j=pre[i]; j!=i; j=pre[j])                     falg[j]=true;                //当前环缩点结束,形成新的图G',跳出继续求G'的最小树形图 ,累计入sum。            }            if( i==n){               for( i=0; i<n; i++)                    if( !flag[i])                        sum+=map[pre[i]][i];               break;           }    }                 return sum;        }

0 0