zoukankan      html  css  js  c++  java
  • HDU3605 Escape (最大流+缩点)

    2012如果这是世界末日怎么办?我不知道怎么做。但现在科学家们发现,有些恒星可以生存,但有些人却不适合生活在一些星球上。现在科学家们需要你的帮助,就是确定所有的人都能在这些星球上生活。

    输入

    多组测试数据,每个数据的开头是n(1<=n<=10万),m(1<=m<=10)n表示地球上有n个人,m代表m星球,行星和人的标签都是从0开始的。这里有n行,每行代表一个适合居住的人,每行有m个数字,第i个数字是1,表示一个人适合居住在第i个星球,或者是0,表示这个人不适合居住在第i个星球。

    最后一行有m个数字,第i个数字ai表示第i个星球最多能容纳ai人。。

    0<=ai<=100000

    输出

    决定是否所有的人都能不辜负这些明星

    如果可以输出YES,否则输出NO。

    点数很多,但是考虑到每个人只有1000种选择方案,可以缩点后跑网络流,时间复杂度是合理的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+100;
    const ll inf=1e18;
    int n,m;
    struct node {
        int u,v,nxt;
        ll w;
    }edge[maxn<<1];
    int head[maxn],tot;
    void addedge (int u,int v,ll w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
        
        edge[tot].u=v;
        edge[tot].v=u;
        edge[tot].w=0;
        edge[tot].nxt=head[v];
        head[v]=tot++;
    }
    
    ll dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t;
    bool bfs () {
        for (int i=0;i<=t;i++) {
            cur[i]=head[i];
            dep[i]=inf;
            inq[i]=0;
        }
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (q.size()) {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].nxt) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inq[v]==0) {
                        q.push(v);
                        inq[v]=1;
                    }
                }
            }
        }
        if (dep[t]!=inf) return 1;
        return 0;
    }
    ll dfs (int u,ll flow) {
        ll increase=0;
        if (u==t) {
            wjm=1;
            maxflow+=flow;
            return flow;
        }
        ll used=0;
        for (int i=cur[u];i!=-1;i=edge[i].nxt) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            } 
        }
        return used;
    }
    ll Dinic () {
        while (bfs()) {
            wjm=1;
            while (wjm==1) {
                wjm=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    int main () {
    //    源点为0
    //    1~n为人
    //    n+1~n+m为行星
    //    n+m+1为汇点 
    //    源点向每个人连一条容量为1的边
    //    每个人向可以居住的行星连一条容量为1的边
    //    每个行星向汇点连一条容量为a(i)的边 
        while (~scanf("%d%d",&n,&m)) {
            map<vector<int> ,int> mp;
            for (int i=1;i<=n;i++) {
                vector<int> tt;
                for (int j=1;j<=m;j++) {
                    int x;
                    scanf("%d",&x);
                    tt.push_back(x);
                }
                mp[tt]++;
            }
            s=0;
            t=mp.size()+m+1;
            for (int i=0;i<=t;i++) head[i]=-1;tot=0;wjm=0;maxflow=0;
            int cnt=0;
            for (auto it=mp.begin();it!=mp.end();it++) {
                cnt++;
                addedge(s,cnt,it->second);
                vector<int> tt=it->first;
                for (int i=0;i<tt.size();i++) if (tt[i]==1) addedge(cnt,mp.size()+i+1,it->second);
            }
            
            for (int i=1;i<=m;i++) {
                ll x;
                scanf("%lld",&x);
                addedge(mp.size()+i,t,x);
            } 
        //    printf("%lld
    ",Dinic());
            if (Dinic()==n)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
    }
  • 相关阅读:
    LeetCode 242. Valid Anagram (验证变位词)
    LeetCode 205. Isomorphic Strings (同构字符串)
    LeetCode 204. Count Primes (质数的个数)
    LeetCode 202. Happy Number (快乐数字)
    LeetCode 170. Two Sum III
    LeetCode 136. Single Number (落单的数)
    LeetCode 697. Degree of an Array (数组的度)
    LeetCode 695. Max Area of Island (岛的最大区域)
    Spark中的键值对操作
    各种排序算法总结
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14026207.html
Copyright © 2011-2022 走看看