最小生成树kruskal,回溯例题

本文介绍了Kruskal和Prim两种图论算法在构建最小生成树上的区别,Prim基于顶点,Kruskal基于边,以及如何在实际问题中如组合优化(如情感增进和Perket美食配料选择)中应用这些算法。
摘要由CSDN通过智能技术生成

kruskal与prim的不同

kruskal的实现与prim不同,prim采用的是邻接矩阵,而kruskal采用并查集的方法来解决问题,prim的实现是根据顶点来连接,而kruskal是根据边来实现连接,所以kruskar适用于边少的情况。

#include <bits/stdc++.h>
using namespace std;
int fa[5010];
typedef struct note
{
  int x,y,z;
}Note;
Note N[2000010];
int n,m;
int get_root(int x)//寻根
{
    return fa[x]==x?x:fa[x]=get_root(fa[x]);
}
bool cmp(Note a,Note b)
{
    return a.z<b.z;
}
int main()
{
    long long sum=0;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>N[i].x>>N[i].y>>N[i].z;
    }
    sort(N+1,N+m+1,cmp);//对权值排序
    for(int i=0;i<=n;i++)
    {
        fa[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        int x=get_root(N[i].x);
        int y=get_root(N[i].y);
        if(x==y)//避免成环
            continue;
        fa[x]=y;
        sum+=N[i].z;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(i==fa[i])
            ans++;
    }
    if(ans>1)//如果头节点大于1,说明至少有一个顶点到不了
        cout<<"orz";
    else
        cout<<sum;
    return 0;
}

 

回溯练习题 

P2080 增进感情

题目背景

小明和小红的感情,是慢慢发展起来的。

题目描述

他们对对方分别有一个好感值。定义两人的亲密程度为两人的好感值之和。

如果他们的亲密程度达到 v,则他们将走到一起。他们以后的生活将取决于两人的好感值之差的绝对值,这个值越小,他们的生活将越幸福。

现在,他们对对方的好感值都为 00,小明有 n 件事可以干,每件事可以增加他对小红的好感 ai​ 点,并且增加小红对他的好感 bi​ 点。(可能为负数)

小明可以任选一些事做,请你帮小明求出怎样才能让他们的生活更加幸福(求出两人在一起的前提下,好感值之差的最小绝对值即可)。

输入格式

第一行,两个正整数 n,v。

之后 n 行,每行两个空格隔开的整数 ai​,bi​。

输出格式

一行,一个非负整数,表示两人在一起的前提下,好感值之差的最小绝对值。如果无论如何两人也无法在一起,输出 -1

输入输出样例

输入 #1复制

4 15
5 6
-1 8
7 2
1 0

输出 #1复制

3

说明/提示

数据范围与约定
  • 对于 20%20% 数据,保证 0n≤10。
  • 对于 100%100% 数据,保证 1≤n≤30,1≤∣ai​∣,∣bi​∣≤100。

这个题和组合问题差不多,套用一下就行了。 

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[35];
int b[35];
int n,v;
int len[5];
int minn=0x3f3f3f3f;
void dfs(int num,int A1,int B1)
{
     if((A1+B1)>=v)
     {

         int k=abs(A1-B1);
         if(k<minn)
            minn=k;
     }
      for(int i=num;i<=n;i++)
      {

          A1+=a[i];
          B1+=b[i];
          dfs(i+1,A1,B1);
          A1-=a[i];
          B1-=b[i];

      }
}
int main()
{
    cin>>n>>v;
    for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i];
     dfs(1,0,0);
     if(minn==0x3f3f3f3f)
        cout<<-1;
     else
    cout << minn << endl;
    return 0;
}

P2036 [COCI2008-2009 #2] PERKET 

题目描述

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

输入格式

第一行一个整数 n,表示可供选用的食材种类数。

接下来 n 行,每行 22 个整数 si​ 和 bi​,表示第 i 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

输入输出样例

输入 #1复制

1
3 10

输出 #1复制

7

输入 #2复制

2
3 8
5 8

输出 #2复制

1

输入 #3复制

4
1 7
2 6
3 8
4 9

输出 #3复制

1

说明/提示

数据规模与约定

对于 100%100% 的数据,有 1≤�≤101≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×1091×109,酸度和苦度不同时为 11 和 00。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[35];
int b[35];
int n,v;
int len[5];
int minn=0x3f3f3f3f;
void dfs(int num,int A1,int B1)
{

      for(int i=num;i<=n;i++)
      {

          A1*=a[i];
          B1+=b[i];
          minn=min(minn,abs(A1-B1));
          dfs(i+1,A1,B1);
          A1/=a[i];
          B1-=b[i];

      }
      return ;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i];
     dfs(1,1,0);
    cout << minn << endl;
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值