zoukankan      html  css  js  c++  java
  • BZOJ 1066[SCOI2007]蜥蜴

    学了ISAP说我来做一道网络流的傻逼题吧然后自己变成了一个傻逼。。

    De了很久的bug然后发现我从源点向每只蜥蜴连了INF的边,喵喵喵?

    最近写博客好像比较敷衍,还是说一下。每个柱子拆点,源点向每个有蜥蜴的真点连1的边,每个真点向假点连石柱高的边,每个假点向它能到达的柱子的真点连INF的边,每个能跳出去的柱子向汇点连INF的边。

    跑得比Dinic慢。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    typedef long long LL;
    using namespace std;
    const int maxn=20000+25;
    const int INF=0x7fffffff;
    int tot,r,c,D,s,t,n,d[maxn],fir[maxn],cur[maxn],cnt[maxn],p[maxn],a[maxn],is[maxn],ecnt=1;
    char ss[50][50];
    struct edge {
        int from,to,cap,flow,nxt;
        edge(){}
        edge(int from,int to,int cap,int flow,int nxt):from(from),to(to),cap(cap),flow(flow),nxt(nxt){}
    }e[maxn*2];
    void add(int u,int v,int w) {
        e[++ecnt]=edge(u,v,w,0,fir[u]);
        e[++ecnt]=edge(v,u,0,0,fir[v]);
        fir[u]=ecnt-1; fir[v]=ecnt;
    }
    queue<int>que;
    void bfs() {
        for(int i=1;i<=n;i++) d[i]=n;
        d[t]=0; que.push(t);
        while(!que.empty()) {
            int x=que.front(); que.pop();
            for(int i=fir[x];i;i=e[i].nxt) 
                if(d[e[i].to]==n&&e[i].flow==e[i].cap) {
                    d[e[i].to]=d[x]+1;
                    que.push(e[i].to);
                }
        }
    }
    int cal() {
        int res=INF;
        for(int x=t;x!=s;x=e[p[x]].from) 
            res=min(res,e[p[x]].cap-e[p[x]].flow);
        for(int x=t;x!=s;x=e[p[x]].from) {
            e[p[x]].flow+=res;
            e[p[x]^1].flow-=res;
        }
        return res;
    }
    int Maxflow() {
        bfs();
        for(int i=1;i<=n;i++) cur[i]=fir[i],cnt[d[i]]++;
        int res=0;
        for(int x=s;d[x]<n;) {
            if(x==t) {
                res+=cal();
                x=s;
            }
            int ok=0;
            for(int &i=cur[x];i;i=e[i].nxt) 
            if(d[e[i].to]+1==d[x]&&e[i].flow<e[i].cap){
                p[x=e[i].to]=i;ok=1;break;    
            }
            if(!ok) {
                cur[x]=fir[x]; int M=n;
                for(int i=fir[x];i;i=e[i].nxt) 
                if(e[i].cap>e[i].flow){M=min(M,d[e[i].to]+1);}
                if(!(--cnt[d[x]])) break;
                cnt[d[x]=M]++;
                if(x!=s) x=e[p[x]].from;
            }
        }
        return res;
    }
    double dis(int x,int y,int xx,int yy) {return sqrt((double)(x-xx)*(x-xx)+(double)(y-yy)*(y-yy));}
    void ADD(int x,int y) {
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++) 
            if(i==x&&j==y) continue;
            else if(dis(x,y,i,j)<=(double)D) add(r*c+(x-1)*c+y,(i-1)*c+j,INF);
        add((x-1)*c+y,r*c+(x-1)*c+y,a[(x-1)*c+y]);
        if(min(x,r-x+1)<=D||min(y,c-y+1)<=D) add(r*c+(x-1)*c+y,t,INF);
    }
    void init() {
        scanf("%d%d%d",&r,&c,&D);
        s=r*c*2+1; t=r*c*2+2; n=t;
        for(int i=1;i<=r;i++) {
            for(int j=1;j<=c;j++) {
                char ch=getchar();
                while(ch<'0'||ch>'9') ch=getchar();
                a[(i-1)*c+j]=ch-'0';
            }
        }
        for(int i=1;i<=r;i++) {
            for(int j=1;j<=c;j++) {
                char ch=getchar();
                while(ch!='.'&&ch!='L') ch=getchar();
                if(ch=='L') {tot++; add(s,(i-1)*c+j,1);}
            }
        }
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++) 
                ADD(i,j);
    }
    void work() {
        printf("%d
    ",tot-Maxflow());
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    英语:漏屋-英语学习的真实方法及误区分析(转)
    TSP(旅行者问题)——动态规划详解(转)
    用二进制位表示状态,从而将状态压缩到一个整数里表示
    Android的CursorLoader用法小结
    RMQ问题ST算法 (还需要进一步完善)
    离散化
    反转(开关问题) POJ 3276
    关于序列中某个元素位置的查找
    快速幂运算
    Docker学习2-虚拟化
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7535695.html
Copyright © 2011-2022 走看看