hdu Escape

Escape

题目:

非常裸的多重匹配。

可是点数较多,所以要用到状态压缩。

。。

。。

第一次写。

好厉害的赶脚。

#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;

const int INF = 1 << 30;
const int MAXN = 20000 + 10;

//////////////////////////////
struct Edge{
   int from,to,cap,flow;
   Edge(){};
   Edge(int _from,int _to,int _cap,int _flow)
       :from(_from),to(_to),cap(_cap),flow(_flow){};
};
vector<Edge> edges;
vector<int> G[MAXN];
int d[MAXN],cur[MAXN];
int N,M,src,sink;

////////////////////////////

int dp[MAXN];

void init(){
    src = (1 << M) + M + 2; sink = src + 1;
    for(int i = 0;i < sink + 2;++i)
        G[i].clear();
    edges.clear();
}

void addEdge(int from,int to,int cap){
    edges.push_back(Edge(from,to,cap,0));
    edges.push_back(Edge(to,from,0,0));
    int sz = edges.size();
    G[from].push_back(sz - 2);
    G[to].push_back(sz - 1);
}

void build(){
     int x;
     memset(dp,0,sizeof(dp));

     for(int i = 0;i < N;++i){
        int sum = 0;
        for(int j = 0;j < M;++j){
            scanf("%d",&x);
            if(x) sum += (1 << j);
        }
        dp[sum]++;             //第几个集合
     }

     for(int i = 0;i < M;++i){
        scanf("%d",&x);
        addEdge((1 << M) + i,sink,x);
     }

     for(int i = 0;i < (1 << M);++i)if(dp[i]){
        addEdge(src,i,dp[i]);
        for(int j = 0;j < M;++j){
            if(i & (1 << j)){          //推断该星球是否属于该集合
                addEdge(i,(1 << M) + j,dp[i]);
            }
        }
     }
}

bool BFS(){
    fill(d,d+sink+2,-1);
    queue<int> Q;
    Q.push(src);
    d[src] = 0;

    while(!Q.empty()){
        int x = Q.front(); Q.pop();
        for(int i = 0;i < (int)G[x].size();++i){
            Edge& e = edges[G[x][i]];
            if(d[e.to] == -1&&e.cap > e.flow){
                d[e.to] = d[x] + 1;
                Q.push(e.to);
            }
        }
    }
    return d[sink] > 0;
}

int DFS(int x,int a){
    if(x == sink||a == 0)
        return a;

    int flow = 0,f;
    for(int& i = cur[x];i < (int)G[x].size();++i){
        Edge& e = edges[G[x][i]];
        if(d[e.to] == d[x] + 1&&(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 flow = 0;
    while(BFS()){
        memset(cur,0,sizeof(cur));
        flow += DFS(src,INF);
    }
    return flow;
}

int main(){
//    freopen("Input.txt","r",stdin);

    while(scanf("%d%d",&N,&M) == 2){
         init();
         build();

         int flow = maxFlow();

         if(flow < N){
            puts("NO");
         } else {
            puts("YES");
         }
    }
    return 0;
}

试写了一个二分多重匹配,时间在该题上差点儿相同。第一次写这个多重匹配,凭着感觉写了一个。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 100000 + 10;
int G[MAXN][15];
int match[15][MAXN],up[15],Link[15];
bool used[15];
int N,M;

bool dfs(int u){
   for(int v = 0;v < M;++v){
        if(G[u][v] && !used[v]){
            used[v] = 1;
            if(Link[v] < up[v]){
                match[v][Link[v]++] = u;
                return true;
            } else {
                for(int i = 0;i < Link[v];++i){
                    if(dfs(match[v][i])){
                       match[v][i] = u;
                       return true;
                    }
                }
            }
        }
   }

   return false;
}

void solve(){
    int res = 0;
    bool flag = false;
    memset(match,-1,sizeof(match));
    memset(Link,0,sizeof(Link));

    for(int i = 0;i < N;++i){
        memset(used,0,sizeof(used));
        if(!dfs(i)){
            res++;
            flag = true;        ///提前退出,反超时!

!!!!

!1
            break;
        }
    }
    if(flag){
        puts("NO");
    } else {
       puts("YES");
    }
}
int main()
{
  //  freopen("Input.txt","r",stdin);

    while(scanf("%d%d",&N,&M) == 2){
         memset(G,0,sizeof(G));
         for(int i = 0;i < N;++i){
            for(int j = 0;j < M;++j){
                scanf("%d",&G[i][j]);
            }
         }

         for(int i = 0;i < M;++i)
            scanf("%d",&up[i]);

         solve();
    }
    return 0;
}
时间: 2024-10-12 20:53:26

hdu Escape的相关文章

hdu 3605 Escape 二分图的多重匹配(匈牙利算法)

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

HDU 5389 Zero Escape(dp啊 多校啊 )

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5389 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi (you may hear about ever17?) and developed by Chunsoft. Stilwell is enjoying the first chapter of

HDU 1733 Escape(分层网络流)

HDU 1733 Escape 题目链接 题意:给定一个图,#是墙,@是出口,.可以行走,X是人,每个时间每个格子只能站一个人,问最少需要多少时间能让人全部撤离(从出口出去) 思路:网络流,把每个结点每秒当成一个结点,这样枚举时间,每多一秒就在原来的网络上直接加一层继续增广即可,注意考虑方向的时候,要考虑上原地不动 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorit

HDU 1593 find a way to escape

find a way to escape Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1389    Accepted Submission(s): 508 Problem Description 一日,话说0068与***泛舟湖上.忽见岸边出现他的一大敌人elnil.0068当然不想落入elnil的魔爪,于是他就得想办法逃脱. 这

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 最大流+状压

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7145    Accepted Submission(s): 1553 Problem Description 2012 If this is the end of the

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