51Nod 1757(二分&网络流)

二分答案,用网络流去判断,这个时间是否可行。m遍dfs求出每个非洞口节点到每个洞口的距离。设置一个虚拟源点和汇点,建图时把在x时间内可以到达洞口的点与洞口连一条容量为1 的边。把每个洞口分成x个点,连向汇点,容量为1.把每个非洞口节点与源点连一条边,容量为1。每个洞口的第i个节点向第i+1个节点连一条无穷大的边,然后就只要判断汇点的流量是否为n-m就行啦。

    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  

    using namespace std;  
    const int N=2010;  
    const int mod=100000000;  
    const int MOD1=1000000007;  
    const int MOD2=1000000009;  
    const double EPS=0.00000001;  
    typedef long long ll;  
    const ll MOD=1000000007;  
    const int INF=1000000010;  
    const ll MAX=1ll<<55;  
    const double pi=acos(-1.0);  
    typedef double db;  
    typedef unsigned long long ull;  
    int n,m,q[N],d[50],dis[50][N];  
    int tot,u[100*N],v[500*N],pre[500*N],cap[500*N],flow[500*N];  
    void add(int a,int b) {  
        v[tot]=b;pre[tot]=u[a];u[a]=tot++;  
        v[tot]=a;pre[tot]=u[b];u[b]=tot++;  
    }  
    void dfs(int a,int b,int fa) {  
        dis[a][b]=dis[a][fa]+1;  
        for (int i=u[b];i!=-1;i=pre[i])  
        if (v[i]==fa) continue ;  
        else dfs(a,v[i],b);  
    }  
    void add_edge(int a,int b,int c,int f) {  
        v[tot]=b;cap[tot]=c;flow[tot]=f;pre[tot]=u[a];u[a]=tot++;  
        v[tot]=a;cap[tot]=0;flow[tot]=0;pre[tot]=u[b];u[b]=tot++;  
    }  
    bool bo[100*N];  
    int f[100*N],di[100*N],head[100*N];  
    bool BFS(int a,int b) {  
        int i,l=1,r=1;  
        memset(bo,0,sizeof(bo));  
        f[1]=a;bo[a]=1;di[a]=0;  
        for (;l<=r;l++)  
            for (i=u[f[l]];i!=-1;i=pre[i])  
            if (!bo[v[i]]&&cap[i]>flow[i]) bo[v[i]]=1,f[++r]=v[i],di[v[i]]=di[f[l]]+1;  
        return bo[b];  
    }  
    int DFS(int a,int b,int en) {  
        if (a==en||b==0) return b;  
        int ret=0,f;  
        for (int& i=u[a];i!=-1;i=pre[i])  
        if (di[v[i]]==di[a]+1&&(f=DFS(v[i],min(b,cap[i]-flow[i]),en)>0)) {  
            flow[i]+=f;flow[i^1]-=f;  
            b-=f;ret+=f;if (!b) break ;  
        }  
        return ret;  
    }  
    int judge(int a) {  
        int i,j,S=0,T=n+a*m+1,sum=0;  
        tot=0;memset(u,-1,sizeof(u));  
        for (i=1;i<=n;i++) if (!q[i]) add_edge(S,i,1,0);  
        for (i=1;i<=m;i++) {  
            for (j=1;j<=a;j++) add_edge(n+(i-1)*a+j,T,1,0);  
            for (j=1;j>1;  
        while (l+1>1;  
        else l=mid,mid=(l+r)>>1;  
        printf("%d\n", r);  
        return 0;  
    }  


你可能感兴趣的:(图论)