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. 三星 note3销售地查询、销售地代码

    查看销售地代码 用KIES验销售地:记下设定-关于-状态里的序号. 手机不要连接电脑,注意是不要连接,打开KIES3,点工具——固件恢复和初始化,输入大写的型号SM-N900或者SM-N9005,确认 ...

  2. DateTime日期格式获取 分类: C# 2014-04-15 10:36 233人阅读 评论(0) 收藏

    c#.net 获取时间年月日时分秒格式 //获取日期+时间 DateTime.Now.ToString();            // 2008-9-4 20:02:10 DateTime.Now. ...

  3. SAP-MM:创建采购组织、采购组

    创建采购组织 路径:SPRO – IMG – 企业结构 – 定义 – 物料管理 – 维护采购组织   操作: Step 1.点击"新条目". Step 2.维护"采购组织 ...

  4. Codeforces 112B-Petya and Square(实现)

    B. Petya and Square time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  5. DFU工作过程中USB机制

    在一级bootloader执行进入USB启动方式之后,设备进行枚举.枚举过程中会通过PC端发送命令对连接的USB设备进行枚举.当枚举成功之后,在PC端可以看到设备的盘符. 当设备能够被PC正确识别之后 ...

  6. Git 版本控制工具使用介绍------Windows系统下使用

    Git 是用于 Linux内核开发的版本控制工具.与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持(wingeddevil注:这得分是用什 ...

  7. Android(java)学习笔记242:多媒体之设置全屏的方法

    在实际的应用程序开发中,我们有时需要把 Activity 设置成全屏显示,一般情况下,可以通过两种方式来设置全屏显示效果.其一,通过在代码中可以设置,其二,通过manifest配置文件来设置全屏. 其 ...

  8. 请输出in.txt文件中的2 4 6 8 9 10 12行

    in.txt文件: 学号 姓名 性别 年龄 1001 张三 男 18 1002 赵四 男 19 1003 李丽 女 18 1004 刘芳 女 32 1005 王五 男 54 1006 小明 男 32 ...

  9. javaScript特效

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  10. shareSDK微博分享出现: 分享失败: 错误描述:Insufficient app permissions! 错误码:10014

    这个错误是由于appKey所在账号没有微博高级写入接口权限, 需要申请, 详见: http://www.mamicode.com/info-detail-936938.html