/* Name: 最大树形图 Copyright: no Author: Moon@whu Date: 24-10-06 14:06 Description: 树形图定义为没有两条弧指向同一个顶点的有向树,即不含环, 且存在一个根可以延有向弧到达任何一个节点。 求有向图的最大树形图,即找到该图的一个支撑子图满足: 1。该支撑子图为一个树形图 2。在所有这样的支撑子图中边权和最大。 ----程序写的很烂,只能求最大权,不能确定所生产的树形图-,- */ #include <stdio.h> #include <string.h> #include <vector> #define maxL 1200 using namespace std; typedef struct ybk{ int i,c;}Point; vector <Point> gtlink[maxL]; //逆图 int n,m,top; int flag[maxL]; //当前节点属于那个环 int up[maxL]; //指向当前节点权最大弧的另一节点 int maxF[maxL]; //指向当前节点的最大弧权 int tl; inline int get(int it) { while(flag[it]==it) return it; int k = get(flag[it]); flag[it] = k; return k; } inline int find(int it) { while(up[it]!=it) it = get(up[it]); return it; } int main() { int i,j,k,t; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0; i<=2*n; i++) gtlink[i].clear(); for(i=0; i<m; i++){ scanf("%d%d%d",&j,&k,&t); Point at; at.i = j; at.c = t; gtlink[k].push_back(at); } for(i=1; i<=2*n; i++) up[i] = flag[i] = i; top = n; tl = 0; for(i=1; i<=top; i++) { int max,maxi=-1,min; for(j=0; j<gtlink[i].size(); j++) if( maxi==-1||gtlink[i][j].c>max ){ max = gtlink[i][j].c; maxi = gtlink[i][j].i; } if( maxi==-1/*||max<0 最大分支*/) continue; maxi = get(maxi); maxF[i] = max; tl += max; if( find(maxi)==i ){ up[i] = maxi; min = max; maxi = i; do{ //标记节点环所属环标号为top+1,并求该环内最小弧 flag[maxi] = top+1; if(maxF[maxi]<min) min = maxF[maxi]; up[maxi] = get(up[maxi]); maxi = up[maxi]; }while(maxi!=top+1); //ps: up[i] = top+1 now.. maxi = i; tl -= min; do{ for( j=0; j<gtlink[maxi].size(); j++ )//更新指向当前弧的权值 { int t = gtlink[maxi][j].i; t = get(t); if( t == top+1 ) continue; //同一环内的弧不做更新 gtlink[maxi][j].c -= (maxF[maxi]-min); gtlink[top+1].push_back(gtlink[maxi][j]);//新合成定点加弧 } maxi = up[maxi]; }while( maxi!=top+1); top++;//更新节点总数--含人工节点 } else up[i] = maxi; } k = 0; for(i=1; i<=top; i++)//k为根的个数,显然若k>1,则原图不存在最大生成树形图 if(up[i]==i) k++; if(k>1) printf("Error/n"); else printf("%d/n",tl); } return 0; } -------- 程序没有经过严格测试,且确定所生产的树的每条边较为困难。 望路过的达人指点 ~_~ 发表于: 2006-10-24,修改于: 2006-10-24 14:20