HDU 4685 Prince and Princess

强连通分量,看大神的题解才会写的....

http://www.cnblogs.com/kuangbin/p/3261157.html

数据量有点大,第一次Submit 2995ms过的,时限3000ms,差一点就TLE了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 2000 + 10;
int N, M;
vector<int>Cun[maxn];
vector<int>G[maxn];
vector<int>FG[maxn];
int nx, ny, Time, Block;
int g[maxn][maxn];
int cx[maxn], cy[maxn];
int mk[maxn];
int flag[maxn], dfn[maxn], Belong[maxn];
struct Point
{
    int id, dfn;
} point[maxn];

int Scan()
{
    int res = 0, ch, flag = 0;

    if ((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if (ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while ((ch = getchar()) >= '0' && ch <= '9')
        res = res * 10 + ch - '0';

    return flag ? -res : res;
}

bool cmp(const Point&a, const Point&b)
{
    return a.dfn>b.dfn;
}

int path(int u)
{
    for (int v = 1; v <= ny; v++)
    {
        if (g[u][v] && !mk[v])
        {
            mk[v] = 1;
            if (cy[v] == -1 || path(cy[v]))
            {
                cx[u] = v;
                cy[v] = u;
                return 1;
            }
        }
    }
    return 0;
}

int MaxMatch()
{
    int res = 0;
    memset(cx, -1, sizeof(cx));
    memset(cy, -1, sizeof(cy));
    for (int i = 1; i <= nx; i++)
    {
        if (cx[i] == -1)
        {
            memset(mk, 0, sizeof(mk));
            res = res + path(i);
        }
    }
    return res;
}

void dfs(int now)
{
    flag[now] = 1;
    for (int i = 0; i<G[now].size(); i++)
    if (!flag[G[now][i]])
        dfs(G[now][i]);
    Time++;
    dfn[now] = Time;
}

void Dfs(int now)
{
    Belong[now] = Block;
    for (int i = 0; i<FG[now].size(); i++)
    if (!Belong[FG[now][i]])
        Dfs(FG[now][i]);
}

int main()
{
    int CA;
    CA = Scan();
    for (int er = 1; er <= CA; er++){
        N = Scan();
        M = Scan();
        memset(flag, 0, sizeof(flag));
        memset(dfn, 0, sizeof(dfn));
        memset(Belong, 0, sizeof(Belong));
        Time = 0, Block = 0;
        for (int i = 0; i<maxn; i++) G[i].clear();
        for (int i = 0; i<maxn; i++) Cun[i].clear();
        for (int i = 0; i<maxn; i++) FG[i].clear();
        memset(g, 0, sizeof(g));
        nx = N, ny = M;

        for (int i = 1; i <= N; i++)
        {
            int ToT, To;
            ToT = Scan();
            while (ToT--)
            {
                To = Scan();
                Cun[i].push_back(To);
                g[i][To] = 1;
            }
            sort(Cun[i].begin(), Cun[i].end());
        }
        int res = MaxMatch();

        memset(g, 0, sizeof(g));
        int A = M - res, B = N - res;//A表示虚拟王子数量,B表示虚拟妹子数量
        nx = N + A, ny = M + B;
        if (B>0)//王子有单身
        {
            for (int j = M + 1; j <= M + B; j++)
            for (int i = 1; i <= N; i++)
            {
                g[i][j] = 1;
                G[i].push_back(j + nx);
                FG[j + nx].push_back(i);
            }
        }
        if (A>0)
        {
            for (int i = N + 1; i <= N + A; i++)
            for (int j = 1; j <= M; j++)
            {
                g[i][j] = 1;
                G[i].push_back(j + nx);
                FG[j + nx].push_back(i);
            }
        }
        for (int i = 1; i <= N; i++)
        for (int j = 0; j<Cun[i].size(); j++)
        {
            g[i][Cun[i][j]] = 1;
            G[i].push_back(Cun[i][j] + nx);
            FG[Cun[i][j] + nx].push_back(i);
        }
        MaxMatch();
        for (int i = 1; i <= ny; i++)
        if (cy[i] != -1)
        {
            G[i + nx].push_back(cy[i]);
            FG[cy[i]].push_back(i + nx);
        }

        for (int i = 1; i <= nx + ny; i++) if (!dfn[i]) dfs(i);
        for (int i = 0; i<nx + ny; i++) point[i].id = i + 1, point[i].dfn = dfn[i + 1];
        sort(point, point + nx + ny, cmp);
        for (int i = 0; i<nx + ny; i++)
        if (!Belong[point[i].id])
            Block++, Dfs(point[i].id);
        int RT;
        int ans[maxn];
        printf("Case #%d:\n", er);
        for (int i = 1; i <= N; i++)
        {
            RT = 0;
            for (int j = 0; j<Cun[i].size(); j++)
            {
                if (Belong[i] == Belong[Cun[i][j] + nx])
                {
                    ans[RT] = Cun[i][j];
                    RT++;
                }
            }
            printf("%d", RT);
            for (int x = 0; x<RT; x++) printf(" %d", ans[x]);
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2015-09-01 17:11  Fighting_Heart  阅读(154)  评论(0编辑  收藏  举报