Cod sursa(job #1671135)

Utilizator lupvasileLup Vasile lupvasile Data 1 aprilie 2016 13:07:11
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.57 kb
#include <bits/stdc++.h>
using namespace std;
#ifdef INFOARENA
#define cout fout
#endif // INFOARENA
ifstream fin("sakura.in");
ofstream fout("sakura.out");
/// ////////////////////////////////

#define nmax 502

int dp[nmax][nmax],L[nmax],R[nmax];
bool open[nmax];
vector<int> G[nmax];

class copacel
{
public:
    vector<int> at_lev[nmax],G[nmax];
    int lev[nmax],n,sz[nmax];

    void grow()
    {
        int i,x,y;
        fin>>n;
        for(i=0; i<n; ++i) G[i].clear(),at_lev[i].clear(),lev[i]=0,sz[i]=0;

        for(i=1; i<n; ++i)
        {
            fin>>x>>y;
            G[x].push_back(y);
            G[y].push_back(x);
        }
    }

    void bloom(int nod)
    {
        at_lev[lev[nod]].push_back(nod);
        sz[nod]=1;

        for(auto son:G[nod])
        {
            if(sz[son]) continue;
            lev[son]=lev[nod]+1;
            bloom(son);
            sz[nod]+=sz[son];
        }
    }

} brad,mar;

bool cupleaza(int nod)
{
    if(open[nod]) return 0;

    for(auto vec:G[nod])
        if(L[vec]==-1)
    {
        L[vec]=nod;
        R[nod]=vec;
        return 1;
    }

    open[nod]=true;
    for(auto vec:G[nod])
        if(cupleaza(L[vec]))
        {
            L[vec]=nod;
            R[nod]=vec;
            open[nod]=false;
            return 1;
        }


    open[nod]=false;
    return 0;
}

bool try_match(int x,int y)
{
    if(mar.G[y].size()==1 && y) return 1;
    //if(brad.G[x].size() <mar.G[y].size()) return 0;

    for(auto sonX:brad.G[x]) R[sonX]=-1,open[sonX]=0;
    for(auto sonY:mar.G[y]) L[sonY]=-1;

    for(auto sonX:brad.G[x])
            if(R[sonX]==-1)
                cupleaza(sonX);

    int nr=(x!=0);
    for(auto sonX:brad.G[x])
        if(R[sonX]!=-1) ++nr;

    return nr==mar.G[y].size();
}


void make_din()
{
    if(brad.n<mar.n)
    {
        dp[0][0]=0;
        return;
    }

    memset(dp,0,sizeof dp);
    for(int i=0;i<brad.n;++i) G[i].clear();

    for(int i=mar.n-1;i>=0;--i)
        for(auto x:brad.at_lev[i])
            for(auto y:mar.at_lev[i])
                if(brad.sz[x]>=mar.sz[y])
                    {
                        dp[x][y]=try_match(x,y);
                        if(dp[x][y]) G[x].push_back(y);
                    }

}

int main()
{
    int T;
    fin>>T;
    for(; T; --T)
    {
        brad.grow();
        mar.grow();

        brad.bloom(0);
        mar.bloom(0);

        make_din();

        if(dp[0][0]) cout<<brad.n-mar.n<<'\n';
        else cout<<"-1\n";
    }
    return 0;
}