zoukankan      html  css  js  c++  java
  • 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; }


     

  • 相关阅读:
    2018 ACM 网络选拔赛 徐州赛区
    2018 ACM 网络选拔赛 焦作赛区
    2018 ACM 网络选拔赛 沈阳赛区
    poj 2289 网络流 and 二分查找
    poj 2446 二分图最大匹配
    poj 1469 二分图最大匹配
    poj 3249 拓扑排序 and 动态规划
    poj 3687 拓扑排序
    poj 2585 拓扑排序
    poj 1094 拓扑排序
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6938022.html
Copyright © 2011-2022 走看看