HDU 3551 Hard Problem
http://acm.hdu.edu.cn/showproblem.php?pid=3551
题意:给出一个图,还有一个子图的度数,求有没有办法通过删边使得原图的度数变成那个子图的度数?
思路:我们考虑把每个点拆成du[i]-d[i]个点,代表要删去的度数,然后对于每条边,我们建立两个点eu,ev,eu与ev连边,如果这条边连接了i,j两个点,那么所有的i的点向eu连边,所有的j向ev连边,如果有完美匹配(就是所有点都有匹配)那么有解。
至于为什么:如果eu和ev是匹配边,代表这条边不删,因为这条边的两侧,也就是连接的两个点都有其他的匹配了,那么这条边就不用删。
如果这条边不是匹配边,那么说明i和eu匹配了,j和ev匹配了,这条边代表删掉了,而i和j的度数也-1了
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
struct edge{
int u,v;
}e[];
int n,m,p[],q[];
int match[],newbase;
int inqueue[],inpath[],G[][],inblossom[],father[];
int du[],d[],c[],base[],start,finish,head,tail;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
int lca(int u,int v){
memset(inpath,,sizeof inpath);
while (){
u=base[u];
inpath[u]=;
if (!match[u]) break;
u=father[match[u]];
}
while (){
v=base[v];
if (inpath[v]) break;
v=father[match[v]];
}
return v;
}
void reset(int u){
while (u!=newbase){
int v=match[u];
inblossom[base[v]]=inblossom[base[u]]=;
u=father[v];
if (base[u]!=newbase) father[u]=v;
}
}
void blossomcontract(int u,int v){
newbase=lca(u,v);
memset(inblossom,,sizeof inblossom);
reset(u);
reset(v);
if (base[u]!=newbase) father[u]=v;
if (base[v]!=newbase) father[v]=u;
for (int i=;i<=n;i++)
if (inblossom[base[i]]){
base[i]=newbase;
if (!inqueue[i]) c[++tail]=i,inqueue[i]=;
}
}
void findaugmentingpath(){
memset(inqueue,,sizeof inqueue);
memset(father,,sizeof father);
for (int i=;i<=n;i++) base[i]=i;
head=;tail=;c[]=start;inqueue[start]=;
finish=;
while (head<=tail){
int u=c[head++];
for (int v=;v<=n;v++)
if (G[u][v]&&base[u]!=base[v]&&match[v]!=u){
if (v==start||(match[v]>)&&(father[match[v]]>)){
blossomcontract(u,v);
}else
if (father[v]==){
father[v]=u;
if (match[v]){
c[++tail]=match[v];inqueue[match[v]]=;
}else{
finish=v;
return;
}
}
}
}
}
void augmentpath(){
int u,v,w;
u=finish;
while (u>){
v=father[u];
w=match[v];
match[u]=v;
match[v]=u;
u=w;
}
}
bool solve(){
int res=;
memset(match,,sizeof match);
for (int i=;i<=n;i++)
if (!match[i]){
start=i;
findaugmentingpath();
if (finish) augmentpath(),res++;
}
for (int i=;i<=n;i++)
if (!match[i]) return ;
return ;
}
bool build(){
memset(G,,sizeof G);
int cnt=;
for (int i=;i<=n;i++)
if (du[i]>d[i]) return ;
memset(p,,sizeof p);
for (int i=;i<=m;i++){
if (!p[e[i].u]){
p[e[i].u]=++cnt;
q[e[i].u]=cnt+d[e[i].u]-du[e[i].u]-;
cnt=cnt+d[e[i].u]-du[e[i].u]-;
}
if (!p[e[i].v]){
p[e[i].v]=++cnt;
q[e[i].v]=cnt+d[e[i].v]-du[e[i].v]-;
cnt=cnt+d[e[i].v]-du[e[i].v]-;
}
int k=cnt+;cnt+=;
G[k][k-]=G[k-][k]=;
for (int j=p[e[i].u];j<=q[e[i].u];j++) G[j][k-]=G[k-][j]=;
for (int j=p[e[i].v];j<=q[e[i].v];j++) G[j][k]=G[k][j]=;
}
n=cnt;
return ;
}
int main(){
int Tcase=;
int T=read();
while (T--){
n=read();m=read();
printf("Case %d: ",++Tcase);
memset(d,,sizeof d);
for (int i=;i<=m;i++){
e[i].u=read();e[i].v=read();
d[e[i].u]++;d[e[i].v]++;
}
for (int i=;i<=n;i++) du[i]=read();
if (build()&&solve()){
printf("YES\n");
}else{
printf("NO\n");
}
}
return ;
}
HDU 3551 Hard Problem的更多相关文章
- HDU 3549 Flow Problem(最大流)
HDU 3549 Flow Problem(最大流) Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...
- hdu 5106 Bits Problem(数位dp)
题目链接:hdu 5106 Bits Problem 题目大意:给定n和r,要求算出[0,r)之间全部n-onebit数的和. 解题思路:数位dp,一个ct表示个数,dp表示和,然后就剩下普通的数位d ...
- HDU 3374 String Problem (KMP+最大最小表示)
HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others) Memory ...
- hdu 5105 Math Problem(数学)
pid=5105" target="_blank" style="">题目链接:hdu 5105 Math Problem 题目大意:给定a.b ...
- Hdu 5445 Food Problem (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online)
题目链接: Hdu 5445 Food Problem 题目描述: 有n种甜点,每种都有三个属性(能量,空间,数目),有m辆卡车,每种都有是三个属性(空间,花费,数目).问至少运输p能量的甜点,花费 ...
- 网络流 HDU 3549 Flow Problem
网络流 HDU 3549 Flow Problem 题目:pid=3549">http://acm.hdu.edu.cn/showproblem.php?pid=3549 用增广路算法 ...
- HDU 1022 Train Problem I
A - Train Problem I Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u ...
- HDU 3374 String Problem(KMP+最大/最小表示)
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 3549 Flow Problem
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Description Network flow is a well- ...
随机推荐
- C#的dictionary使用总结
Dictionary<string, string>是一个泛型,本身有集合的功能有时候可以把它看成数组. 他的结构是这样的:Dictionary<[key], [value]> ...
- Fiddler 抓包 教程
Fiddler的基本介绍 Fiddler的官方网站: www.fiddler2.com Fiddler官方网站提供了大量的帮助文档和视频教程, 这是学习Fiddler的最好资料. Fiddler是最 ...
- Open-source Project官方地址
非常遗憾因为这篇博文是专门搜集各个开源项目的各种官方连接地址的,所以链接较多,csdn不同意保存. 请点击这里下载. 因为我的积分不多了,所以这个文档须要一个积分..应该不多吧...确实没有积分的童鞋 ...
- iTunes 11.2更新下载:改善播客阅读
昨日,苹果公布了iTunes 11.2更新,新版别改善了播客阅读的方法,让用户能够在新的"未播映的"标签中疾速找到没有赏识的单集,其他功用包括主动删去现已播映的单集,并可在&quo ...
- 各种div+css居中方式调整(转载)
盘点8种CSS实现垂直居中水平居中的绝对定位居中技术 分类: 前端开发2013-09-11 21:06 24959人阅读 评论(3) 收藏 举报 绝对居中垂直居中水平居中CSS居中代码 目录(?) ...
- [转] openjdk和jdk的区别与联系
使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的openjdk,那么到底什么是openjdk,它与sun jdk有什么关系和区别呢? 历史上的 ...
- 几句话实现导航栏透明渐变 – iOS
首先我们来看下效果 一开始当我们什么只设置了一张图片作为它的头部视图的时候,它是这样的 首当其冲的,我们先得把导航栏弄透明 那么我们首先得知道,设置navigationBar的BackgroundCo ...
- C#解leetcode 18. 4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...
- Sql语句 不支持中文 国外数据库
由于老美的不支持中文 SQL 语句第一:字段类型改为nvarchar,ntext 第二:强制转化 N update dbo.Role set rolename=N'普通用户' update dbo.T ...
- 从一个SVN下载的导入另一个SVN里面
如果项目是你从个一个SVN下载的,你想存入另一个SVN里面 那么问题来了 你用eclipse的team的时候会发现没有Team share 这个选项,那么就等于是没有上传的选项了 解决办法,把项目删掉 ...