2020牛客暑期多校训练营(第一场)I.1 or 2

2020牛客暑期多校训练营(第一场)I.1 or 2

题目链接:https://ac.nowcoder.com/acm/contest/5666/I

题意:给你一个n个点m条边的无向图,通过删除一些边使每个点的度数满足di,若存在则输出Yes,否则输出No。

通过拆点来跑一般图的最大匹配,将度数为2的点进行拆点,拆完的点连向对应的x,y点。如果达到完美匹配,这条边的另一头必定匹配着另一个点的一个度,表示拆点原点相连,这样一条边的匹配是合乎要求的。

思路来源:https://www.cnblogs.com/xiongtao/p/11189452.html

#include
using namespace std;
#define ll long long
const int maxn=1050;
bool g[maxn][maxn],inque[maxn],inpath[maxn];
bool inhua[maxn];
int st,ed,newbase,ans,n;
int base[maxn],pre[maxn],match[maxn];
int head,tail,que[maxn];
int x[maxn],y[maxn],f[maxn],mp[maxn][maxn],ne,np;
void Push(int u){
    que[tail]=u;
    tail++;
    inque[u]=1;
}
int Pop(){
    int res=que[head];
    head++;
    return res;
}
int lca(int u,int v){
    memset(inpath,0,sizeof(inpath));
    while(1){
        u=base[u];
        inpath[u]=1;
        if(u==st) break;
        u=pre[match[u]];
    }
    while(1){
        v=base[v];
        if(inpath[v]) break;
        v=pre[match[v]];
    }
    return v;
}
void reset(int u){
    int v;
    while(base[u]!=newbase){
        v=match[u];
        inhua[base[u]]=inhua[base[v]]=1;
        u=pre[v];
        if(base[u]!=newbase) pre[u]=v;
    }
}
void contract(int u,int v){
    newbase=lca(u,v);
    memset(inhua,0,sizeof(inhua));
    reset(u);
    reset(v);
    if(base[u]!=newbase) pre[u]=v;
    if(base[v]!=newbase) pre[v]=u;
    for(int i=1;i<=n;i++){
        if(inhua[base[i]]){
            base[i]=newbase;
            if(!inque[i])
                Push(i);
        }
    }
}
void findaug(){
    memset(inque,0,sizeof(inque));
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=n;i++)
        base[i]=i;
    head=tail=1;
    Push(st);
    ed=0;
    while(head0)&&pre[match[v]]>0)
                    contract(u,v);
                else if(pre[v]==0){
                    pre[v]=u;
                    if(match[v]>0)
                        Push(match[v]);
                    else{
                        ed=v;
                        return ;
                    }
                }
            }
        }
    }
}
void aug(){
    int u,v,w;
    u=ed;
    while(u>0){
        v=pre[u];
        w=match[v];
        match[v]=u;
        match[u]=v;
        u=w;
    }
}
void edmonds(){
    memset(match,0,sizeof(match));
    for(int u=1;u<=n;u++){
        if(match[u]==0){
            st=u;
            findaug();
            if(ed>0)aug();
        }
    }
}
void create(){
    n=0;
    memset(g,0,sizeof(g));
    for(int i=1;i<=np;i++)
        for(int j=1;j<=f[i];j++)
            mp[i][j]=++n;
    for(int i=0;i

你可能感兴趣的:(2020牛客暑期多校训练营(第一场)I.1 or 2)