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的更多相关文章

  1. HDU 3549 Flow Problem(最大流)

    HDU 3549 Flow Problem(最大流) Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...

  2. hdu 5106 Bits Problem(数位dp)

    题目链接:hdu 5106 Bits Problem 题目大意:给定n和r,要求算出[0,r)之间全部n-onebit数的和. 解题思路:数位dp,一个ct表示个数,dp表示和,然后就剩下普通的数位d ...

  3. HDU 3374 String Problem (KMP+最大最小表示)

    HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory ...

  4. hdu 5105 Math Problem(数学)

    pid=5105" target="_blank" style="">题目链接:hdu 5105 Math Problem 题目大意:给定a.b ...

  5. Hdu 5445 Food Problem (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online)

    题目链接: Hdu  5445 Food Problem 题目描述: 有n种甜点,每种都有三个属性(能量,空间,数目),有m辆卡车,每种都有是三个属性(空间,花费,数目).问至少运输p能量的甜点,花费 ...

  6. 网络流 HDU 3549 Flow Problem

    网络流 HDU 3549 Flow Problem 题目:pid=3549">http://acm.hdu.edu.cn/showproblem.php?pid=3549 用增广路算法 ...

  7. HDU 1022 Train Problem I

    A - Train Problem I Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  8. HDU 3374 String Problem(KMP+最大/最小表示)

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. hdu 3549 Flow Problem

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Description Network flow is a well- ...

随机推荐

  1. sparkSQL1.1入门之二:sparkSQL执行架构

          在介绍sparkSQL之前.我们首先来看看,传统的关系型数据库是怎么执行的.当我们提交了一个非常easy的查询: SELECT a1,a2,a3 FROM tableA Where con ...

  2. Qt深入:不能不知道的Type、Attribute和Flags

    Qter高手与新手的区别在于:知道还是不知道 Qt不是开发语言,所以无所谓谁厉害.但使用他的Qter却有着差异,也许是面向对象语言本身的.或者实际经验上的.而对于Qt本身来说,高手与新手最显著的差异在 ...

  3. QT程序库

      实际上,QT不仅仅是一个巨大的程序库,而是7个程序库,还包括许多使用工具,qmake是其中的一个.如今,术语GUI工具包代表的东西的用途不再仅仅是系统提供的那么一个小部分(GUI界面).尤其是QT ...

  4. 安全框架Shiro和Spring Security比较

    Shiro 首先Shiro较之 Spring Security,Shiro在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势. Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证. ...

  5. 异步tcp通信——APM.ConsoleDemo

    APM测试 俗话说麻雀虽小,五脏俱全.apm虽然简单,但是可以实现单机高性能消息推送(可以采用redis.kafka等改造成大型分布式消息推送服务器). 测试demo: using System; u ...

  6. Android内存泄漏的各种原因详解

    转自:http://mobile.51cto.com/abased-406286.htm 1.资源对象没关闭造成的内存泄漏 描述: 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我 ...

  7. Android中SQLite使用

    现在的主流移动设备像Android.iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上 ...

  8. HTTPS双向认证

    生成证书 openssl genrsa -des3 -out server.key 2048 openssl req -new -x509 -key server.key -out ca.crt -d ...

  9. Linux基本权限

    首先需要我们了解的是,权限(rwx)对于文件和目录的作用是不一样的 . 权限对文件的作用 r : 读取文件内容(cat , more , head , tail) w: 编辑.新增.修改文件内容(vi ...

  10. 关于Core Data的一些整理(三)

    关于Core Data的一些整理(三) 关于Core Data Stack的四种类与它们的关系如下: NSManagedObjectModel NSPersistentStore NSPersiste ...