HDU 3605 —— Escape 状态压缩+最大流

原题:http://acm.hdu.edu.cn/showproblem.php?pid=3605

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<algorithm>
#define inf 1e9
using namespace std;
const int maxn = 1500;
const int maxm = 15000;
int n, m;
int num_nodes;
int can[15];
int tmp[maxn];

struct Edge
{
    int from, to, flow, cap;
}edge[maxm*2];  

vector<int>G[maxn];
int edgenum;
void add(int u, int v, int c)
{
    edge[edgenum].from = u;
    edge[edgenum].to = v;
    edge[edgenum].flow = 0;
    edge[edgenum].cap = c;
    edgenum++;  

    edge[edgenum].from = v;
    edge[edgenum].to = u;
    edge[edgenum].flow = 0;
    edge[edgenum].cap = 0;
    edgenum++;  

    G[u].push_back(edgenum-2);
    G[v].push_back(edgenum-1);
}  

int deep[maxn];
bool vis[maxn];
void BFS(int s, int t)
{
    queue<int>Q;
    memset(vis, false, sizeof vis);
    Q.push(t);
    vis[t] = true;
    deep[t] = 0;
    while(!Q.empty())
    {
        int now = Q.front();
        Q.pop();
        for(int i = 0;i<(int)G[now].size();i++)
        {
            int v = edge[G[now][i]].to;
            if(!vis[v])
			{
                deep[v] = deep[now] + 1;
                vis[v] = true;
                Q.push(v);
            }
        }
    }
}  

int gap[maxn];
int cur[maxn];
int front[maxn];
int Augment(int s, int t)
{
    int minflow = inf;
    int begin = t;
    while(begin != s)
    {
        Edge& e = edge[front[begin]];
        minflow = min(minflow, e.cap - e.flow);
        begin = e.from;
    }  

    begin = t;
    while(begin != s)
    {
        edge[front[begin]].flow += minflow;
        edge[front[begin]^1].flow -= minflow;
        begin = edge[front[begin]].from;
    }
    return minflow;
}  

int Maxflow(int s, int t)
{
    int flow = 0;
    BFS(s, t);
    memset(gap, 0, sizeof gap);
    memset(cur, 0, sizeof cur);
    for(int i = 0;i<num_nodes;i++)  gap[deep[i]]++;
    int begin = s;
    while(deep[s] < num_nodes)
    {
        if(begin == t)
		{
            flow += Augment(s, t);
            begin = s;
        }
        bool flag = false;
        for(int i = cur[begin];i<(int)G[begin].size();i++)
        {
            Edge& e = edge[G[begin][i]];
            if(e.cap > e.flow && deep[begin] == deep[e.to] + 1)
			{
                front[e.to] = G[begin][i];
                cur[begin] = i;
                flag = true;
                begin = e.to;
                break;
            }
        }
        if(!flag)
        {
            int k = num_nodes-1;
            for(int i = 0;i<(int)G[begin].size();i++)
			{
                Edge& e = edge[G[begin][i]];
                if(e.cap > e.flow)
                    k = min(k, deep[e.to]);
            }
            if(--gap[deep[begin]] == 0) break;
            gap[deep[begin] = k+1]++;
            cur[begin] = 0;
            if(begin != s)
                begin = edge[front[begin]].from;
        }
    }
    return flow;
}  

void init()
{
    for(int i = 0;i<num_nodes+2;i++) G[i].clear();
    edgenum = 0;
    memset(deep, 0, sizeof deep);
}

int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		memset(tmp, 0, sizeof tmp);
		for(int i = 0;i<n;i++)
		{
			int k = 0;
			for(int j = 0;j<m;j++)
			{
				int x;
				scanf("%d", &x);
				if(x)	k |= 1<<j;
			}
			tmp[k]++;
		}
		for(int i = 0;i<m;i++)	scanf("%d", &can[i]);
		int s = 0, t = (1<<m)+m+1;
		num_nodes = t+1;
		init();
		for(int i = 0;i<(1<<m);i++)
		{
			if(tmp[i])
			add(s, i+1, tmp[i]);
		}
		for(int i = 0;i<m;i++)
			add((1<<m)+i+1, t, can[i]);
		for(int i = 0;i<(1<<m);i++)
		{
			for(int j = 0;j<m;j++)
			{
				if(i & (1<<j))
				add(i+1, (1<<m)+j+1, tmp[i]);
			}
		}
		int flow = Maxflow(s, t);
		if(flow == n)	printf("YES\n");
		else	printf("NO\n");
	}
	return 0;
}
时间: 2024-10-17 09:41:53

HDU 3605 —— Escape 状态压缩+最大流的相关文章

Escape(状态压缩+最大流,好题)

Escape http://acm.hdu.edu.cn/showproblem.php?pid=3605 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 13201    Accepted Submission(s): 3329 Problem Description 2012 If this is the end of the wor

hdu 3605 网络流 状态压缩

/*Author :usedrose */ /*Created Time :2015/8/27 1:45:04*/ /*File Name :2.cpp*/ #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <iostream> #include <algorithm> #include <sstream> #include

HDU 3605 Escape(最大流+缩点转换)

http://acm.hdu.edu.cn/showproblem.php?pid=3605 题目很简单,要求的就是最后能搬到星球上去的人的个数.刚开始看到,知道是最大流,就把人和星球都设为点,能生存就连线,权值为1,最后建立超级源点和超级汇点.求出最大流量即可.先是RE,开大数组后TLE.仔细算了,光光人到星球的便就可达到100w了,超时的概率太大了.后来找了解题报告,知道了缩点这一说,因为星球个数m最大只有10个,所以每个人最多只有1024种情况,把这每一种情况设为点(这里很抽象),将之与符

Hdu 3605 Escape (最大流 + 缩点)

题目链接: Hdu 3605  Escape 题目描述: 有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功? 解题思路: 正常情况下建图,不会爆内存,但是TLE还是稳稳的.以前只遇到过网络流拆点建图,这个正好是缩点建图.吼吼吼~~~,建图的方式还是值得学习的. 因为星球数目最多十个,那么无论有多少个人,其不同选择也就2^10种咯.把不同的选择作为节点,节点就从10^5减少到了2^10,整整缩小了一个数量级呢.建立源点和汇点,源点和选择链接,边权为这种选

hdu 4568(状态压缩dp)

题意:一张n*m的网格内每个点有话费,还有若干个宝藏,问一个人要走进去拿走所有宝藏在走出来的最小花费. 思路:看宝藏只有13个直接想到了状压dp[i][j]拿了哪几个前一个为j的最小花费,先bfs+优先队列预处理出最短路,然后记忆化搜索就可. 代码如下: 1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao

HDU 3605 Escape【二分图多重匹配】

题意: 有n个人去m个星球  告诉你每个人想去哪些星球和每个星球最多容纳多少人,问能不能让所有人都满足 分析: 二分图多重匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 100005; 8 const int maxm = 15; 9 10

hdu 3605 Escape (二分图多重匹配)

Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4298    Accepted Submission(s): 1129 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient

HDU 3605 Escape (最大流)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do

HDU 3605 Escape(状压+最大流)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 9430    Accepted Submission(s): 2234 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient