题目链接:点击查看

题目大意:给出一张无向图,问能否删除任意数量的边,使得每个点的度数都达到指定的数值

题目分析:参考博客:https://www.cnblogs.com/xiongtao/p/11189452.html

很巧妙的建图,需要拆度+拆边建图,如第一个样例而言:

4 4

1 2

3 4

2 3

1 4

1 2 1 0

建图为:

点 1 代表节点 1 的一个度,点 2 和点 3 代表节点 2 的一个度,点 4 代表节点 3 的一个度

剩下的结点 5 ~ 节点 12 都是对每条边的拆点

对于每条边而言,只需要将相应的 度拆点 都连好就ok了,建好图后跑一般图的最大匹配,如果每个点都能恰好匹配的话,那么答案就是 yes 了

大概解释如下,对于每条边而言,最大匹配只有两种情况,第一种是,两端的度拆点分别和两个边拆点被匹配,这样代表了这条边需要留在原图中,也就是需要被使用,另一种情况是只有边拆点的两个点被匹配,代表着这条边在原图中应该被删除

实现就比较简单了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e3+100;const int M=N*N*2;int x[N],y[N],du[N],id[N][N];int n,m,que[M],ql,qr,pre[N],tim=0;struct edge
{int v,nxt;
}e[M];int h[N],tot=0;int match[N],f[N],tp[N],tic[N];int find(int x)
{return f[x]==x?f[x]:f[x]=find(f[x]);
}void addedge(int u,int v)
{e[++tot]=(edge){v,h[u]};h[u]=tot;
}int lca(int x,int y)
{for (++tim;;swap(x,y)) if(x) {x=find(x);if(tic[x]==tim) return x; else {tic[x]=tim;x=pre[match[x]];}}
}void shrink(int x,int y,int p)
{while(find(x)!=p) {pre[x]=y;y=match[x];if(tp[y]==2) {tp[y]=1;que[++qr]=y;}if(find(x)==x) f[x]=p;if(find(y)==y) f[y]=p;x=pre[y];}
}bool aug(int s)
{for(int i=1;i<=n;++i) f[i]=i;memset(tp,0,sizeof tp);memset(pre,0,sizeof pre);tp[que[ql=qr=1]=s]=1; // 1: type A ; 2: type Bint t=0;while(ql<=qr) {int x=que[ql++];for(int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {if(find(v)==find(x)||tp[v]==2) continue; if(!tp[v]) {tp[v]=2;pre[v]=x;if(!match[v]) {for(int now=v,last,tmp;now;now=last) {last=match[tmp=pre[now]];match[now]=tmp,match[tmp]=now;}return true;} tp[match[v]]=1,que[++qr]=match[v];} else if(tp[v]==1) {int l=lca(x,v);shrink(x,v,l);shrink(v,x,l);}}}   return false;
}int solve()
{int ans=0;for(int i=1;i<=n;i++)if(!match[i]&&aug(i))ans++;return ans;
}void init()
{tot=0;memset(id,0,sizeof(id));memset(match,0,sizeof(match));memset(tic,0,sizeof(tic));memset(h,0,sizeof(h));
}void build()
{int cnt=0;for(int i=1;i<=n;i++)for(int j=1;j<=du[i];j++)id[i][j]=++cnt;for(int i=1;i<=m;i++){addedge(cnt+1,cnt+2);addedge(cnt+2,cnt+1);for(int j=1;j<=du[x[i]];j++){addedge(id[x[i]][j],cnt+1);addedge(cnt+1,id[x[i]][j]);}for(int j=1;j<=du[y[i]];j++){addedge(cnt+2,id[y[i]][j]);addedge(id[y[i]][j],cnt+2);}cnt+=2;}n=cnt;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){init();scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d",x+i,y+i);for(int i=1;i<=n;i++)scanf("%d",du+i);build();if(solve()*2==n)printf("Case %d: YES\n",++kase);elseprintf("Case %d: NO\n",++kase);}return 0;
}

HDU - 3551 Hard Problem(一般图最大匹配)相关推荐

  1. [转]带花树,Edmonds's matching algorithm,一般图最大匹配

    看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树--其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...

  2. hdu A + B Problem II(大数相加,数组实现)

    hdu A + B Problem II(大数相加,数组实现) 题目走起 注意最后一个case 不需要换行 下面代码 #include<stdio.h> #include<strin ...

  3. 【学习小记】一般图最大匹配——带花树算法

    Text 一般图的最大匹配仍然是基于寻找增广路的 增广路的定义是这样的一条路径,它不经过重复的点,并且路径两端均没有匹配,且整条路径是非匹配边-匹配边-非匹配边这样交错的. 类比二分图最大匹配的增广路 ...

  4. URAL - 1099 Work Scheduling(一般图最大匹配-带花树模板)

    题目链接:点击查看 题目大意:给出n个警卫,接下来给出数个关系,表示两个警卫可以互相配合,现在规定只有可以互相配合的警卫才能留下来继续工作,问最多能有多少个警卫留下来工作,输出匹配方案 题目分析:一般 ...

  5. 一般图最大匹配——带花树

    所谓花,就是如下图所示的一个奇环: 本文中粗边代表现在的匹配边,细边代表该点的前驱(后文会讲解前驱是什么,现在只需要知道每个点和它的前驱在原图中一定是有边的). 如图所示,一朵包含\(2k+1\)个点 ...

  6. HDU.1001 Sum Problem

    原题 HDU.1001 Sum Problem 分类 杂题 题意 计算从1到正整数n的累加和. 输入/输出 要求与格式 输入内容 每行输入一个正整数 输出结果 结果为累加和 输出格式 每个输出结果独占 ...

  7. [HDU 5445]Food Problem[多重背包]

    题目链接:[HDU 5445]Food Problem[多重背包] 题意分析: 有n种类型的点心,每种提供t的能量,占据u的空间,有v个: 有m种类型的卡车,每种容量x,雇佣花费y,能提供z辆: 点心 ...

  8. HDU - 4687 Boke and Tsukkomi(一般图最大匹配-带花图)

    题目链接:点击查看 题目大意:给出n个人和m对匹配,现在问有多少组匹配是不必要的,按照升序输出答案 题目分析:因为题目给的N比较小,所以一开始我的想法是先计算出最大匹配,而后枚举每一条边被删除,然后计 ...

  9. hdu 4160 Dolls 匈牙利算法求最大匹配

    Dolls                                                                               Time Limit: 2000 ...

最新文章

  1. R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(配置边界颜色)实战
  2. ssh中linux 变颜色,linux – 如何通过SSH在Vim中启用颜色?
  3. RocketMQ最佳实战
  4. python智能办公系统_用 Python 自动化办公能做到哪些有趣或有用的事情?
  5. 【tensorflow】安装cuda10.0 and cudnn 7.5.0 and tensorflow-gpu==1.14.0
  6. 二阶龙格库塔公式推导_DeepFM原理推导
  7. 28 Java类的加载机制、什么是类的加载、类的生命周期、加载:查找并加载类的二进制数据、连接、初始化、类加载器、双亲委派模型、自定义类加载器
  8. Windows 安装 Redis
  9. linux脚本实现多重管道,制作Linux shell时流重定向和管道
  10. Bootstrap表单
  11. 如何建立数据平台?看上市公司的选择!
  12. nodejs做中间层_nodejs做中间层,向后端取数据
  13. 做微信营销你知道男女用微信的习惯吗?
  14. 【转】HTTP幂等性概念和应用
  15. maven简单了解,没有Maven和使用Maven的区别
  16. 音视频技术开发周刊 | 177
  17. commit规范使用gitmoji全流程 cz-customizable+commitlint+husky+conventional-changelog
  18. Oracle table move tablespace
  19. kotlin coroutine源码解析之Job启动流程
  20. python中concat的用法_pandas中concat()的用法

热门文章

  1. MySQ软件的卸载-通过控制面板方式
  2. MySQL sql99语法—左(右)外连接
  3. Nginx的root和alias指令
  4. 并发的发展历史-真空管和穿孔打卡
  5. 高仿真的类-BeanWrapper
  6. 缓存-分布式锁-Redisson简介整合
  7. Redis实现分布式锁释放锁
  8. Zookeeper_实际应用讲解
  9. mysql在linux下配置_mysql数据库在Linux下安装与配置
  10. webfunny前端监控