HDU 3605 Escape

状态压缩+最大流

因为最多只有10个星球,所以人最多只有1<<10种。所以按照人的种类来建图。

此题有毒,光是输入就TLE了,联系了HDU OJ管理员胡杰,把时间放宽为2000ms,最终,用了输入挂,用了C++提交,1200ms过了;不用输入挂 用C++ 1700ms。

 

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

const int maxn = 1500 + 10;
const int INF = 0x7FFFFFFF;

struct Edge
{
    int from, to, cap, flow;
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int n, m, s, t;


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 BFS()
{
    memset(vis, 0, sizeof(vis));
    queue<int>Q;
    Q.push(s);
    d[s] = 0;
    vis[s] = 1;
    while (!Q.empty())
    {
        int x = Q.front();
        Q.pop();
        for (int i = 0; i<G[x].size(); i++)
        {
            Edge& e = edges[G[x][i]];
            if (!vis[e.to] && e.cap>e.flow)
            {
                vis[e.to] = 1;
                d[e.to] = d[x] + 1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}


//加边
void AddEdge(int from, int to, int cap)
{
    Edge r;
    r.from = from;
    r.to = to;
    r.cap = cap;
    r.flow = 0;
    edges.push_back(r);
    Edge d;
    d.from = to;
    d.to = from;
    d.cap = 0;
    d.flow = 0;
    edges.push_back(d);
    m = edges.size();
    G[from].push_back(m - 2);
    G[to].push_back(m - 1);
}

//每个阶段来一次DFS增广
int DFS(int x, int a)
{
    if (x == t || a == 0) return a;
    int flow = 0, f;
    for (int i = cur[x]; i<G[x].size(); i++)
    {
        Edge& e = edges[G[x][i]];
        if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0)
        {
            e.flow += f;
            edges[G[x][i] ^ 1].flow -= f;
            flow += f;
            a -= f;
            if (a == 0) break;
        }
    }
    return flow;
}

//多个阶段,多次建立层次网络。
int Maxflow(int ss, int tt)
{
    int flow = 0;
    while (BFS())
    {
        memset(cur, 0, sizeof(cur));
        flow += DFS(ss, INF);
    }
    return flow;
}


int N, M;
int Tot[maxn];
int Er[maxn];
int zh[maxn];
int ZH[maxn];

int main()
{
    while (scanf("%d%d", &N, &M) != EOF)
    {
        edges.clear();
        for (int i = 0; i<maxn; i++) G[i].clear();
        memset(Tot, 0, sizeof Tot);

        for (int i = 1; i <= N; i++)
        {
            int Ans = 0;
            for (int j = 0; j < M; j++) Er[j] = Scan();
            for (int j = 0; j<M; j++) Ans = Ans + Er[j] * pow(2.0,j);
            Tot[Ans]++;
        }
        s = 1401;
        t = 1400;
        for (int i = 0; i <= (1<<10); i++)
        {
            if (Tot[i])
            {
                AddEdge(s, i, Tot[i]);
                int y = i, q = 0, d = 0;
                while (y) zh[q] = y % 2, y = y / 2, q++;
                for (int ii = 0; ii<q; ii++)
                if (zh[ii])
                    AddEdge(i, 1100 + ii, INF);
            }
        }
        for (int i = 0; i<M; i++)
        {
            int x;
            x = Scan();
            AddEdge(1100 + i, t, x);
        }
        int FF = Maxflow(s, t);
        if (FF != N) printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}

 

posted @ 2015-08-21 10:47  Fighting_Heart  阅读(129)  评论(0编辑  收藏  举报