【bzoj 1693】【bzoj 1741】Asteroids(最小割/最小顶点覆盖)

传送门biu~biu~
把每行建成一个点,每列建成一个点,如果有小行星(x,y)就连一条从x行到y列流量为1的弧。S连每行,流量为1;T连每列,流量为1。最小割即为最少次数。
(18/1/12UPD:最好理解成最小顶点覆盖问题)

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
int n,k,S,T;
int dep[1005],fir[1005],head[1005],nex[50000],to[50000],cap[50000],tp=1;
inline void add(int x,int y,int c){
    nex[++tp]=head[x];
    head[x]=tp;
    to[tp]=y;
    cap[tp]=c;
}
inline int bfs(){
    memset(dep,0,sizeof(dep));
    dep[S]=1;queue<int>q;
    q.push(S);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nex[i]){
            if(cap[i] && !dep[to[i]]){
                dep[to[i]]=dep[x]+1;
                q.push(to[i]);
            }
        }
    }
    return dep[T];
}
int dfs(int x,int now){
    if(x==T || !now)    return now;
    int c=0;
    for(int &i=fir[x];i;i=nex[i]){
        if(dep[to[i]]==dep[x]+1 && cap[i]){
            int f=dfs(to[i],min(now,cap[i]));
            now-=f;
            cap[i]-=f;
            cap[i^1]+=f;
            c+=f;
            if(!now)    break;
        }
    }
    return c;
}
inline int Dinic(){
    int c=0;
    while(bfs()){
        for(int i=1;i<=2*n;++i) fir[i]=head[i];
        fir[S]=head[S];fir[T]=head[T];
        c+=dfs(S,INF);
    }
    return c;
}
int main(){
    scanf("%d%d",&n,&k);S=2*n+1;T=2*n+2;
    for(int i=1;i<=k;++i){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,n+y,1);   add(n+y,x,0);
    }
    for(int i=1;i<=n;++i)   add(S,i,1),add(i,S,0);
    for(int i=1;i<=n;++i)   add(n+i,T,1),add(T,n+i,0);
    printf("%d",Dinic());
    return 0;
}
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页