⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 greedy.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	in.numberofpointattributes	= 0;	in.pointattributelist		= NULL;	in.pointmarkerlist		= NULL;	in.numberofsegments		= 0;	in.numberofholes		= 0;	in.numberofregions		= 0;	in.regionlist			= NULL;	out.pointlist			= NULL;	out.trianglelist		= NULL;	out.neighborlist		= NULL;	triangulate ("znNBQ", &in, &out, &vorout);	if (out.numberoftriangles EQ 0) {		/* There are no triangles (all input points co-linear).		   Compute SMT as straight line segment between points */		minp.x = INF_DISTANCE; maxp.x = -INF_DISTANCE;		minp.y = INF_DISTANCE; maxp.y = -INF_DISTANCE;		for (i = 0; i < pts -> n; i++) {			minp.x = MIN(minp.x, pts -> a [i].x);			maxp.x = MAX(maxp.x, pts -> a [i].x);			minp.y = MIN(minp.y, pts -> a [i].y);			maxp.y = MAX(maxp.y, pts -> a [i].y);		}		free (in.pointlist);		free (out.pointlist);		free (out.trianglelist);		free (out.neighborlist);		return (EDIST(&minp, &maxp));	}	/* Construct edge information */	greedy_edges	= NEWA (out.numberofedges, struct greedy_edge);	triangleedges	= NEWA (3*out.numberoftriangles, int);	for (i = 0; i < 3*out.numberoftriangles; i++) {		triangleedges [i] = -1;	}	ei = 0;	for (i = 0; i < out.numberoftriangles; i++) {		for (j = 0; j < 3; j++) {			p1 = out.trianglelist [3*i + j];			p2 = out.trianglelist [3*i + ((j+1) % 3)];			if (triangleedges [3*i + j] EQ -1) {				/* only add once */				greedy_edges [ei].len	 = EDIST (&(pts -> a [p1]),								  &(pts -> a [p2]));				/* Get BSD info if it is there */				if ((bsdp NE NULL) AND				    (pts -> a [p1].pnum >= 0) AND				    (pts -> a [p2].pnum >= 0)) {					greedy_edges [ei].bsd = bsd (bsdp,								     pts -> a [p1].pnum,								     pts -> a [p2].pnum);				}				else {					greedy_edges [ei].bsd = greedy_edges [ei].len;				}				greedy_edges [ei].p1	 = p1;				greedy_edges [ei].p2	 = p2;				greedy_edges [ei].mst	 = FALSE;				triangleedges [3*i + j]	 = ei;				/* Now go through neighbouring triangles */				/* and add information about the new edge */				for (ni = 0; ni < 3; ni++) {					nt = out.neighborlist [3*i + ni];					if (nt EQ -1) continue;					for (nj = 0; nj < 3; nj++) {						np1 = out.trianglelist [3*nt + nj];						np2 = out.trianglelist [3*nt + ((nj+1) % 3)];						if ((np1 EQ p2) AND						    (np2 EQ p1)) {							 /* found reverse edge */							triangleedges [3*nt + nj] = ei;						}					}				}				++ei;			}		}	}	/* Sort edges */	sortededges = NEWA (out.numberofedges, int);	for (i = 0; i < out.numberofedges; i++) {		sortededges [i] = i;	}	qsort (sortededges, out.numberofedges, sizeof(int), comp_edges);	/* Use Kruskal to find MST */	dsuf_create (&mstsets, pts -> n);	for (i = 0; i < pts -> n; i++) {		dsuf_makeset (&mstsets, i);	}	total_mst_l = 0.0;	for (i = 0; i < out.numberofedges; i++) {		/* go through edges in sorted order */		ei = sortededges [i];		root [1] = dsuf_find (&mstsets, greedy_edges [ei].p1);		root [2] = dsuf_find (&mstsets, greedy_edges [ei].p2);		if (root [1] NE root [2]) {			dsuf_unite (&mstsets, root [1], root [2]);			total_mst_l += greedy_edges [ei].len;			greedy_edges [ei].mst = TRUE; /* remember this edge */		}	}	/* Generate FSTs with 3 and 4 terminals */	greedy_fsts = NEWA (4*out.numberoftriangles, struct greedy_fst);	fst_count = 0;	for (i = 0; i < out.numberoftriangles; i++) {		/* Count the number of MST edges and find their length sum */		mst_count1 = 0;		mst_l1	   = 0.0;		for (j = 0; j < 3; j++) {			ei  = triangleedges [3*i + j];			l[j] = greedy_edges [ei].len;			if (greedy_edges [ei].mst) {				mst_count1++;				mst_l1 += l[j];			}		}		for (j = 0; j < 3; j++) {			terms [j] = out.trianglelist [3*i + j];		}		terms [3] = -1;		/* Do the three terminals induced a connected dubgraph of the MST? */		if (mst_count1 EQ 2) {			/* Yes, so we know the length of the corresponding MST */			mst_l = mst_l1;		}		else {			/* No, they do not. Compute MST for these three terminals */			mst_l = MIN(l[0]+l[1], MIN(l[0]+l[2], l[1]+l[2]));		}		/* Add 3-terminal FST */		add_fst (pts, terms, 3, greedy_fsts, &fst_count, mst_l, (mst_count1 EQ 2));		/* Now go through neighbouring triangles and add */		/* valid FSTs */		for (ni = 0; ni < 3; ni++) {			nt = out.neighborlist [3*i + ni]; /* get triangle index */			if (nt <= i) continue;		  /* only consider once... */			/* Find neighbouring edge and outgoing MST */			/* edge (note that there can be at most one) */			neighbour_edge	   = -1;			neighbour_edge_idx = -1;			mst_count2	   =  0;			for (nj = 0; nj < 3; nj++) {				ei = triangleedges [3*nt + nj];				if (greedy_edges [ei].mst) {					mst_count2++;				}				/* Is this the neighouring edge? */				for (j = 0; j < 3; j++) {					if (triangleedges [3*i + j] EQ ei) {						neighbour_edge	   = ei;						neighbour_edge_idx = nj;					}				}			}			/* Idenfify fourth terminal */			p4 = out.trianglelist [3*nt + ((neighbour_edge_idx + 2) % 3)];			/* Make list of points on border of triangles */			j = -1;			jj = -1;			do {				terms [++jj] = out.trianglelist [3*i + (++j)];			} while (triangleedges [3*i + j] NE neighbour_edge);			terms [++jj] = p4;			while (j < 2) {				terms [++jj] = out.trianglelist [3*i + (++j)];			}			/* Make sure that the two triangles make up a */			/* convex region */			convex_region = TRUE;			for (j = 0; j < 4; j++) {				if (right_turn (&(pts -> a [terms [j]]),						&(pts -> a [terms [(j+1) % 4]]),						&(pts -> a [terms [(j+2) % 4]]))) {					convex_region = FALSE;					break;				}			}			if (NOT convex_region) continue; /* do not try to construct FST */			/* Compute MST for terminals */			mst_l = mst_length(pts, terms, 4);			/* Add 4-terminal FST */			add_fst (pts,				 terms,				 4,				 greedy_fsts,				 &fst_count,				 mst_l,				 (mst_count1 + mst_count2 >= 3));		}	}	/* Sort FSTs */	sortedfsts = NEWA (fst_count, int);	for (i = 0; i < fst_count; i++) {		sortedfsts [i] = i;	}	qsort (sortedfsts, fst_count, sizeof (int), comp_fsts);	/* Use greedy concatenation algorithm:	   1. Use FSTs that span connected subgraphs of MST	   2. Insert not yet tried FSTs into existing tree	*/	new_chosen = NEWA (fst_count, bool);	best_smt_l = INF_DISTANCE;	for (k = -1; k < fst_count; k++) { /* k=-1 means use MST FSTs */		/* Check that FST is not already in current tree */		if ((k >= 0) AND greedy_fsts [ sortedfsts[k] ].chosen) continue;		/* Build union-find structure */		dsuf_create (&fstsets, pts -> n);		for (i = 0; i < pts -> n; i++) {			dsuf_makeset (&fstsets, i);		}		for (i = 0; i < fst_count; i++)			new_chosen[i] = greedy_fsts[i].chosen;		if (k >= 0) {			/* Insert FST number k */			fk = sortedfsts [k];			term_count = greedy_fsts [fk].count;			for (j = 1; j < term_count; j++) {				dsuf_unite (&fstsets,					    dsuf_find (&fstsets, greedy_fsts [fk].p [0]),					    dsuf_find (&fstsets, greedy_fsts [fk].p [j]));			}			total_smt_l = greedy_fsts [fk].len;			new_chosen[fk] = TRUE;		}		else			total_smt_l = 0.0;		/* Go through chosen FSTs (in sorted order) */		for (i = 0; i < fst_count; i++) {			fi = sortedfsts [i];			if (NOT greedy_fsts [fi].chosen) continue;			term_count = greedy_fsts [fi].count;			/* check that no two terminals are in the same block */			in_same_block = FALSE;			for (j = 0; j < term_count; j++) {				root [j] = dsuf_find (&fstsets, greedy_fsts [fi].p [j]);			}			for (j = 0; j < term_count-1; j++) {				for (jj = j+1; jj < term_count; jj++) {					if (root [j] EQ root [jj]) {						in_same_block = TRUE;						break;					}				}			}			if (in_same_block) {				new_chosen [fi] = FALSE;				continue;			}			for (j = 1; j < term_count; j++) {				dsuf_unite (&fstsets,					    dsuf_find (&fstsets, greedy_fsts [fi].p [0]),					    dsuf_find (&fstsets, greedy_fsts [fi].p [j]));			}			total_smt_l += greedy_fsts [fi].len;		}		/* Go through edges in sorted order */		for (i = 0; i < out.numberofedges; i++) {			ei = sortededges [i];			root [1] = dsuf_find (&fstsets, greedy_edges [ei].p1);			root [2] = dsuf_find (&fstsets, greedy_edges [ei].p2);			if (root [1] NE root [2]) {				dsuf_unite (&fstsets, root [1], root [2]);				/* Use BSD length here */				total_smt_l += greedy_edges [ei].bsd;			}		}		dsuf_destroy (&fstsets);		if (total_smt_l < best_smt_l) {			best_smt_l = total_smt_l;			for (i = 0; i < fst_count; i++)				greedy_fsts [i].chosen = new_chosen [i];		}	}	/* Free all allocated arrays, including those allocated by Triangle */	dsuf_destroy (&mstsets);	free (pts);	free (in.pointlist);	free (out.pointlist);	free (out.trianglelist);	free (out.neighborlist);	free (triangleedges);	free (greedy_edges);	free (greedy_fsts);	free (sortededges);	free (sortedfsts);	free (new_chosen);	return (best_smt_l);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -