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\n",Dinic());
        if (Dinic()==n)
            printf("YES\n");
        else
            printf("NO\n");
    }
}

 

posted @ 2020-11-23 18:51  zlc0405  阅读(108)  评论(0编辑  收藏  举报