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\n",tot-Maxflow());
}
int main()
{
    init();
    work();
    return 0;
}
View Code

 

posted @ 2017-09-17 15:15  啊宸  阅读(144)  评论(0编辑  收藏  举报