【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买

目录

题目:修复道路

思路: 

题目:口袋的天空  

思路: 

题目:搭配购买

 思路:


        

        

题目:修复道路

【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买_第1张图片【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买_第2张图片

         

思路: 

判断图的连通性可以用最小生成树,并查集,dfs和bfs。但是后两者都不太适合,并查集的话每合并一次就要判断一次,最小生成树一口气完成就行!
        

#include
using namespace std;
#define re register
const int N=1e3+5,M=1e4+5;
bool f;
struct Edge{ int u,v,t; }e[M];
int fa[N],n,m,ans,cnt,k;

bool cmp(Edge a,Edge b){ return a.t>n>>m>>k;
    for(re int i=1;i<=n;i++) fa[i]=i;//初始化并查集节点
    for(re int i=0;i

        

        

题目:口袋的天空  

        

【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买_第3张图片【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买_第4张图片

        

思路: 

合成k个,然后要最小代价,最小生成树嘛,只需要用掉n-k个边即可

#include//1195
using namespace std;
#define re register
const int N=1e3+5,M=1e4+5;
bool f;
struct Edge{ int u,v,t; }e[M];
int fa[N],n,m,ans,cnt,k;

bool cmp(Edge a,Edge b){ return a.t>n>>m>>k;
    for(re int i=1;i<=n;i++) fa[i]=i;//初始化并查集节点
    for(re int i=0;i

        

        

题目:搭配购买

【算法每日一练]-图论(保姆级教程篇8 最小生成树 ,并查集篇)#修复道路 #口袋的天空 #搭配购买_第5张图片

        

 思路:

就是一道01背包,不过是要先把有关联的云朵合并一下(缩点不就是这样吗),然后再把价值加到祖宗身上。

#include//1455
using namespace std;
int c[10001],d[10001],f[10001];//DP数组
int fa[10001];//并查集数组

int find(int x)
{
    if(x!=fa[x]) {//x自己不是祖宗,就要让fa[x]更新成祖宗的集合号
		fa[x]=find(fa[x]);
	}
    return fa[x];//返回祖先 
}

void unity(int x, int y)
{
    int f1=find(x);
    int f2=find(y);
    fa[f1]=f2;
}

int main()
{
	int n,m,w;
	cin>>n>>m>>w;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=n;i++)
		scanf("%d%d",&c[i],&d[i]);
	int x,y;
	for(int i=1;i<=m;i++)
	{
		cin>>x>>y;
		unity(x,y);
	}

	for(int i=1;i<=n;i++)//将同集合的云朵的价钱与价值都划给祖宗,其余清空
	{
		if(fa[i]!=i)
		{
			d[find(i)]+=d[i];
			d[i]=0;
			c[find(i)]+=c[i];
			c[i]=0;
		}
	}

	for(int i=1;i<=n;i++)
	{
	    for(int v=w;v>=c[i];v--)//01背包
	    {
	    	f[v]=max(f[v],f[v-c[i]]+d[i]);
		}
	}
	cout<

你可能感兴趣的:(图论,算法,图论,深度优先,c++,数据结构,动态规划)