• 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; }


     

  • 相关阅读:
    for 续1
    8 解决多线程对共享数据出错
    7 多线程 全局变量
    6 线程threading
    5 多进程copy文件
    4 进程间通信Queue [kjuː]
    3 进程池
    2 进程multiprocessing [mʌltɪ'prəʊsesɪŋ] time模块
    1 多任务fork Unix/Linux/Mac
    16 pep8 编码规范
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6938022.html
Copyright © 2020-2023  润新知