poj 2831(次小生成树)

题意:给你一幅图,再给你Q个询问,每个询问为id cost,即如果将id这条边的边权改为cost的话,这条边是否可能是最小生成树中的一条边

解题思路:将第i条边(u,v)的权值修改的话,要判断是否是最小生成树中的一条边,首先要把它加入进去,此时必定会引起原来的生成树成环,所以必定要擦去一条边,擦去的是哪一条边,这就利用到了次小生成树的原理了。

之前写过一个次小生成树的题,现在回过头看,感觉又有点不对了。

这里再总结一次:

首先肯定是构造一颗最小生成树,接下来就是枚举不在生成树里的边,假定为(u,v),此时应该把它加入到生成树中,但这样肯定会形成u->v的环路,此时肯定要删除u->v这条环路里的边,删哪一条呢?肯定是除了边(u,v)外的最大边。

现在是如何找到这条最大边,可以采用dp的思想,即dp[i][j]表示在树上i->j的最大值(注意,由于是树,肯定i->j的路径是唯一的)。我们在做Prim算法时,每次都是加入一个顶点S,我们还应该记录下顶点S加入到生成树里,它与谁相连,即我们在更新low[]数组时要记录的。这样,我们可以得到状态方程:dp[i][j] = dp[j][i] = max(dp[j][pre[i]],low[i]),此时i为即将要加入的点,而j是已经在生成树顶点集合里的点。

完成了一次Prim算法,同样也可以将dp数组更新好了,那么回到最开始的问题,删除的边我们就可以直接用dp[u][v]。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 100005;
const int inf = 0x3f3f3f3f;
struct Edge
{
	int u,v,c;
}edge[maxn];
int n,m,q;
int map[1005][1005],path[1005][1005];
int pre[1005],low[1005];
bool vis[1005],used[1005][1005];

int Prim()
{
	int k = 1,ans = 0;
	memset(path,0,sizeof(path));
	memset(vis,false,sizeof(vis));
	memset(used,false,sizeof(used));
	vis[k] = true;
	for(int i = 1; i <= n; i++)
	{
		low[i] = map[k][i];
		pre[i] = k;
	}
	for(int i = 1; i < n; i++)
	{
		int MIN = inf;
		for(int j = 1; j <= n; j++)
			if(vis[j] == false && low[j] < MIN)
			{
				MIN = low[j];
				k = j;
			}
		ans += MIN;
		vis[k] = true;
		used[k][pre[k]] = used[pre[k]][k] = true;
		for(int j = 1; j <= n; j++)
		{
			if(vis[j] == true && j != k)
				path[j][k] = path[k][j] = max(path[j][pre[k]],low[k]);
			if(vis[j] == false && low[j] > map[k][j])
			{
				low[j] = map[k][j];
				pre[j] = k;
			}
		}
	}
	return ans;
}

int main()
{
	while(scanf("%d%d%d",&n,&m,&q)!=EOF)
	{
		memset(map,inf,sizeof(map));
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);
			map[edge[i].u][edge[i].v] = map[edge[i].v][edge[i].u] = min(map[edge[i].u][edge[i].v],edge[i].c);
		}
		int ans = Prim();
		while(q--)
		{
			int id,cost;
			scanf("%d%d",&id,&cost);
			if(path[edge[id].u][edge[id].v] >= cost)
				printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}
时间: 2024-10-08 23:47:51

poj 2831(次小生成树)的相关文章

poj 2831 次小生成树模板

/*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值>=这条边,说明可以替换. prime算法次小生成树模板 */ #include<stdio.h> #include<string.h> #define N 1100 #define inf 0x3fffffff int ma[N][N]; int Min(int a,int b)

POJ 1679 次小生成树

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 30015   Accepted: 10738 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undir

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

Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties

The Unique MST POJ - 1679 次小生成树prim

求次小生成树思路: 先把最小生成树求出来  用一个Max[i][j] 数组把  i点到j 点的道路中 权值最大的那个记录下来 used数组记录该条边有没有被最小生成树使用过   把没有使用过的一条边加入最小生成树必然回形成一条回路   在这条回路中减去 除加入的边的权值最大的一条边  原图必然保持连通  (如果此时 权值最大的边和新加入的边权值相同  则存在 不同的最小生成树) 把每一条边加入再删除后 即可得出次小生成树 参考了: https://blog.csdn.net/qq_3395144

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

Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the followin

POJ 1679:The Unique MST(次小生成树&amp;&amp;Kruskal)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

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

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20293   Accepted: 7124 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

poj 1679 The Unique MST 【次小生成树+100的小数据量】

题目地址:http://poj.org/problem?id=1679 2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2 Sample Output 3 Not Unique! 分析:T组数据,每组n个节点m条边.计算一下,最小生成树是不是独一无二的,如果是就输出最小生成树的权值和,否则输出Not Unique!(不是独一无二的).先计算最小生成树,在计算次小生成树,判断两者的值是否相等!输入数据保证不存在重边. #include <stdi

poj 1679 The Unique MST 【次小生成树】【模板】

题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后添加到最小生成树上,然后把原树上添加了之后形成环的最长的边删去,知道一个最小的.就是次小生成树. 这些需要的都可以在求解最小生成树的时候处理出来. AC代码: #include <cstdio> #include <cstring> #include <iostream> #i