`
人生难得糊涂
  • 浏览: 117418 次
社区版块
存档分类
最新评论

poj1679-次小生成树

 
阅读更多

说下求次小生出树的思路。 先求得最小生成树。

然后枚举不在生成树上的边E(i),将它加入到最小生成树上,则一定会形成一个环,我们把这个环上的最大边删掉,还是一个生成树。得到其权值W(i)  。min(W(i))即是次小生成树

具体实现时这样更简单:求得最小生成树权值min.

求在最小生成树上,任意两点之间的路径上的最大边,并用二维数组maxed[][]记录下来。 (调用多次spfa()实现)。

枚举所有不在生成树上的边,将其加入到最小生成树,并删除掉该环中在最小生成树上的最大边

则可以得到权值为

ans[i] = min+edge[i].w-maxed[u][v]

取ans的最小值即是次小生成树。

 

#include "iostream"
#include "algorithm"
#include "queue"
using namespace  std;
#define  MAXSIZE 110
#define  INF 999999
int t,m,n;
struct node
{
	int u;
	int v;
	int w;
	int flag;
};
node edge[MAXSIZE*MAXSIZE];
queue<int>que;
int f[MAXSIZE];
int e;
int kt;//最小生成树的权值
int vis[MAXSIZE];
int maxed[MAXSIZE][MAXSIZE];
int head[MAXSIZE];
int next[MAXSIZE];
int dis[MAXSIZE];
void addnode(int u,int v,int w,int f)
{
	edge[e].u=u;
	edge[e].v=v;
	edge[e].w=w;
	edge[e].flag=f;
	next[e]=head[u];
	head[u]=e++;

}
bool cmp(node &a,node &b)
{
	return a.w<b.w;
}
int findset(int x)
{
	if (x==f[x])
		return x;
	else
		return f[x]=findset(f[x]);

}
int kruskal()
{
	sort(edge,edge+e,cmp);
	int tot=0;
	int i;
	for (i=1;i<=n;i++)
	{
		f[i]=i;
	}
	for (i=0;i<e;i++)
	{
		if (findset(edge[i].u)!=findset(edge[i].v))
		{
			//union
			f[findset(edge[i].v)]=findset(edge[i].u);
			tot+=edge[i].w;
			edge[i].flag=1;
		}
	}
	return tot;
}
void spfa(int s)
{
	while(!que.empty())
	{
		que.pop();
	}
	memset(vis,0,sizeof(vis));
	que.push(s);
	vis[s]=1;
	int i;
	for (i=1;i<=n;i++)
	{
		dis[i]=INF;
	}
	dis[s]=0;
	while(!que.empty())
	{
		int t=que.front();
		que.pop();
		for ( i=head[t];i!=-1;i=next[i])
		{
			
			if (edge[i].flag&&dis[edge[i].v]>dis[t]+edge[i].w)
			{
				dis[edge[i].v]=dis[t]+edge[i].w;
				if (maxed[s][edge[i].v]<edge[i].w)
				{
					maxed[edge[i].v][s]=maxed[s][edge[i].v]=edge[i].w;
				}
				if (!vis[edge[i].v])
				{
					vis[edge[i].v]=1;
					que.push(edge[i].v);
				}
			}
			
		}
	}
}
int judge()
{
	int min=INF;
	//枚举所有不在生成树上的边
	for (int i=0;i<e;i++)
	{
		if (!edge[i].flag)
		{
			//ans = min+edge[i].w-maxed[u][v]
			int tans=kt+edge[i].w-maxed[edge[i].u][edge[i].v];
			if (min>tans)
			{
				min=tans;
			}
		}
	}
	//cout <<min<<endl;
	return min==kt;
}
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d",&t);
	while(t--)
	{
		e=0;
		scanf("%d%d",&n,&m);
		memset(head,-1,sizeof(head));
		memset(next,-1,sizeof(next));
		memset(maxed,-1,sizeof(maxed));
		while(m--)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			addnode(a,b,c,0);
		}
		//求得最小生成树的权值
		 kt=kruskal();
	//	cout<<"kt: "<<kt<<endl;
		
		//bfs 求得点遍历生成树最大的边
		for (int i=1;i<=n;i++)
		{
			maxed[i][i]=0;
			spfa(i);
		}
		//判断是否具有次小生成树
		if (judge())
			printf("Not Unique!\n");
		else
			printf("%d\n",kt);

	}
	return 0;
}

 

 

 
1
0
分享到:
评论

相关推荐

    次小生成树(POJ 1679 The Unique MST)

    先利用prim算法求出最小生成树,然后通过往MST里加边来判断新生成的最小生成树是否具有最小的权值,POJ上The Unique MST(1679)题是要求判断最小生成树是否唯一,此题其实根本不用这样做,但是为了练习球次小生成树...

    POJ1258-Agri-Net【Prim】

    普里姆算法是一种贪心算法,它从一个顶点开始,逐步扩展最小生成树,每次添加一条与当前生成树连接且权值最小的边。以下是算法的基本步骤: 1. 初始化:选择图中的任意一个顶点作为初始最小生成树的一部分。 2. 建立...

    POJ 1751 求最小生成树prim算法(JAVA)

    标题 "POJ 1751 求最小生成树Prim算法(JAVA)" 提到的是一个编程挑战,涉及图论中的经典算法——Prim算法。在计算机科学中,Prim算法是用于寻找加权无向图的最小生成树的一种有效方法。最小生成树是一棵树形结构,...

    poj 1000 - 2000 部分题目 官方分类

    7. **图算法**:图论是计算机科学中的一大分支,题目可能涵盖DFS、BFS、最小生成树、最短路径等算法。 8. **模拟**:模拟题目要求解题者准确地按照给定的规则执行一系列操作,通常需要细心和耐心。 9. **数据结构...

    POJ1789-Truck History【Prim】

    在图论中,一个连通图的最小生成树是一棵树,它包含图中的所有顶点,并且所有边的权重之和尽可能小。Prim算法是从一个顶点开始,逐步添加边,直到包含所有顶点,每次添加的边都是当前未加入树的边中权重最小的一条。...

    POJ2485-Highways【Prim】

    2. 每次迭代:在未加入到最小生成树的顶点中,找到与已加入顶点相连的边中权值最小的一条,将这条边的另一端顶点加入到最小生成树中。 3. 重复步骤2,直到所有顶点都加入到最小生成树中,或者没有未加入顶点的边。 ...

    POJ3122-Pie

    同时,对于POJ这类在线判题系统,还需要遵循特定的输入输出格式,确保代码能正确读取输入数据并生成符合规范的输出。 总之,"POJ3122-Pie"是一道结合了算法设计和实际编程技巧的题目,通过解题和阅读解题报告,可以...

    POJ2531-Network Saboteur

    4. **最小生成树**:如果涉及网络的基础设施,可能需要找到最小生成树(例如Kruskal's Algorithm或Prim's Algorithm),以最小化破坏成本。 5. **最短路径算法**:Dijkstra's Algorithm或Floyd-Warshall Algorithm...

    POJ2031-Building a Space Station【Prim+计算几何】

    【描述】题目要求构建一个空间站,具体来说是找到最小生成树,以连接一系列在外太空漂浮的模块。这里运用了Prim算法,这是一种寻找图中最小生成树的经典算法,旨在以最小的总边权和连接所有顶点。计算几何则可能涉及...

    POJ 分类题目

    最小生成树算法** - **定义**:包括 Prim 算法和 Kruskal 算法。 - **示例题目**: - poj1789 - poj2485 - poj1258 - poj3026 - **应用场景**:适用于构建最小成本网络、电力线路铺设等问题。 **4. 拓扑排序**...

    POJ3026-Borg Maze【BFS+Prim】

    然后,Prim算法每次从尚未加入最小生成树的节点中选择距离起点最近的一个,连接到树中,更新其他节点的距离。重复此过程,直至所有节点都被包含在内。 在提交的代码文件“POJ3026-Borg Maze【BFS+Prim】.cpp”中,...

    POJ1035-Spell checker

    总的来说,"POJ1035 - Spell checker"不仅是一道编程题目,也是一次对字符串处理、错误检测、算法设计和实现能力的综合检验。参与这样的练习有助于提升编程技能,特别是对于解决实际问题和优化性能的思考。通过阅读...

    poj1251 最小生成树

    在图论中,一个无向图的最小生成树是指连接所有顶点的一棵树,其边的权重之和尽可能小。解决这类问题的常见算法有Prim算法和Kruskal算法。 描述中提到的“NULL”表明没有具体的题目描述,但通常POJ题目会提供一个...

    北大POJ初级-基本算法

    6. **图论算法**:包括图的遍历(深度优先搜索和广度优先搜索)、最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树问题(Prim和Kruskal算法)。 7. **字符串处理**:如KMP算法、Rabin-Karp算法、...

    北大POJ初级-图算法

    5. **Prim算法和Kruskal算法**:这两种都是解决最小生成树问题的算法,适用于无权图或带权重的图。Prim算法从一个节点开始,每次添加一条最小的边,直到连接所有节点;而Kruskal算法则是按边的权重从小到大排序,...

    POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类

    - **解释**:最小生成树算法主要包括Prim算法和Kruskal算法。 ##### (4) 拓扑排序 - **例题**:poj1094 - **解释**:拓扑排序是对有向无环图的一种排序方式,可以用来解决依赖关系的问题。 ##### (5) 匹配算法 - *...

    POJ1000-1299中的80题AC代码

    5. **其他**:位操作、编码解码、模拟、图论问题(最短路径、最小生成树、网络流等)、递归、分治策略等。 每道题目都可能综合运用到多个知识点,而AC代码则代表了解决这些问题的有效方法。通过研究这些代码,我们...

    POJ 1679 练习克鲁斯卡尔kruskal 算法

    在图论领域,克鲁斯卡尔(Kruskal)算法是一种用于解决最小生成树问题的有效方法。这个问题涉及到在一个加权无向图中找到一棵包括所有顶点的树,其边的权重之和尽可能小。POJ 1679 是一个编程竞赛题目,旨在通过实践...

    ACM题目分类.txt

    - **描述**:最小生成树算法包括Prim算法和Kruskal算法。 - **应用场景**:构建连接所有顶点且权重最小的生成树。 - **相关题目**: - POJ 1789 - POJ 2485 - POJ 1258 - POJ 3026 #### 3. 流网络算法 - **描述...

    POJ 1789 最小生成树之prim算法

    标题中的“POJ 1789 最小生成树之prim算法”指的是一个在线编程竞赛题目,来源于普林斯顿开放在线课程(POJ)平台。该题目要求参赛者实现Prim算法,这是一种解决图论问题中寻找最小生成树的经典算法。最小生成树是在...

Global site tag (gtag.js) - Google Analytics