图论考查的总结(1)

一.CF1209D Cow and Snacks

1.本题考查的是并查集(本人考虑的是匈牙利算法 一--一)

    int find(int x){
            if(f[x]!=x) f[x]=find(f[x]);
            return f[x];
    }

        匈牙利算法考查的是二分图的最大匹配问题(脑抽了)

        本题就是在考查连通块个数

2.思路如下:

        第一位客人肯定把他的喜爱口味全会取走,为了让结果更优,接下来的客人的喜爱口味与之有重合,这样他就只会取走一个零食,以此类推……于是建一个n个点m条边的图。第m条边连接ai​,bi​ 两点。显然这样会形成若干个连通块。对于每一个连通块如上述处理,假设该连通块有 x个点,那么该连通块中最终有 x-1位客人可以取走零食。于是答案就变成了统计每个连通块的点数

   for(int i=1;i<=n;i++) f[i]=i;
   while(k--){
        scanf ("%d%d",&x,&y);
        int r1=find(x),r2=find(y);
        if(r1!=r2) f[r1]=r2;
        else ans++;
    }
    printf("%d\n",ans);

然后就结束了(肥肠煎蛋  PS:非常简单0w0)

3.一定要先分析好考查的是哪种问题(血的教训)

二.P2330 繁忙的都市

1.本题考查最小生成树

2.可以用kruskal算法(并查集),其思想如下:

        (1)将边权按照权重从小到大排序

        (2)枚举每条边和权重

struct edge{
    int a,b,w;
    bool operator<(const edge&W) const{
        return w<W.w;
    }
}e[51000];
int find(int x){
    if(f[x]!=x) f[x]=find(f[x]);
    return f[x];
}

3.第一问求选择的道路数,因为只有“保证连通”一个条件优先级在“道路尽量少”之上,不难看出直接输出n-1(一个N个点的联通图最少有n-1条边)。第二问直接在求最小生成树的同时,记录下当前已搜到的最大值。由于此题未要求输出最小生成树的权值和,因此在求最小生成树的过程中直接只记录最大值。

void un(int x,int y){
    int xx=find(x);
    int yy=find(y);
    f[xx]=yy;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        e[i]=(edge){u,v,c};
    }
    for(int i=1;i<=n;i++) f[i]=i;
    sort(e+1,e+m+1);
    for(int i=1;i<=m;i++){
        if(find(f[e[i].a])!=find(f[e[i].b])) {
            un(e[i].a,e[i].b);
            maxx=e[i].w;
            k++;
        }
        if(k==n-1) break;
    }
    cout<<n-1<<" "<<maxx; 
    return 0;
}

The end......

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值