首页 > 代码库 > bzoj 1066(网络流)

bzoj 1066(网络流)

题意

思路:网络流分类里面的题目。。所以自然要想网络流啦。。。由题意可知:蜥蜴在高度>0的柱子上才有行动能力。。所以只要考虑高度大于0的柱子即可。.以图的每根柱子作为点,对于柱子u,如果u能到达的柱子v,就连接(u , v).如果是边有高度。。那么选定一个起点s连接所有蜥蜴的起点,权值设为1。所有能跳出边界的点连接终点t,权值设为inf。容量1代表这条边被经过一次。这样这个图能跳出去的蜥蜴数量就是从s->t的最大流。但是这个图是每个点有容量限制。这种我们可以把点拆成两个。拆点之后得到的两点,假如把u拆成两个(u1,u2),那么边(u1 , u2)的容量就是u的容量,然后把原来顶点指出的边变成出顶点指出,指向原来顶点的边变成从入顶点指入。这道题里面,先拆点,然后建图。注意两根不同柱子之间的容量要设为inf。然后跑一边dinic就好了。

代码:

技术分享
#include<bits/stdc++.h>
#define inf 0x3f3f3ff
using namespace std;
struct Node{int next ,  v , w;}e[500001];
int r , c  ,d , cnt , tot,mp[30][30] ,mark[30][30], head[802] ,lv[802] , it[802];
void ins(int u , int v , int w)
{e[tot].v = v , e[tot].w = w , e[tot].next = head[u] , head[u] = tot++;}
void init()
{tot=0,cnt = 0;memset(head,-1,sizeof(head));}
void Insert(int u ,int v,int w)
{ins(u,v,w);ins(v,u,0);}
bool judge(int x1 , int y1,int x2 , int y2){
    if(x1 <= 0 || y1 <= 0 || x2 <= 0 || y2 <= 0) return 0;
    if((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) <= d&&mp[x1][y1]&&mp[x2][y2]) return 1;
    return 0;
}
void build(){
    for(int x1 = 1;x1 <= r;x1++)
        for(int y1 = 1; y1 <= c;y1++)
            for(int x2 = x1 - d;x2 <= x1 + d;x2++)
            for(int y2 = y1 - d;y2 <= y1 + d;y2++)
                if(judge(x1 , y1 , x2 , y2)) Insert(mark[x1][y1] + 400 , mark[x2][y2],inf);
    for(int x1 = 1; x1 <= r;x1++)
        for(int y1 = 1 ; y1 <= c;y1++)
        if(mp[x1][y1]) Insert(mark[x1][y1] ,mark[x1][y1] + 400 ,mp[x1][y1]);
    for(int x1 = 1; x1 <= r;x1++)
        for(int y1 = 1; y1 <= c;y1++)
        if(min(min(c-y1 + 1,y1) , min(x1 , r - x1 + 1))<= d) Insert(mark[x1][y1] + 400 , 801 , inf);
}
void bfs(int s){
    memset(lv,-1,sizeof(lv));
    queue<int>que;
    lv[s] = 0;
    que.push(s);
    while(!que.empty()){
        int u = que.front(); que.pop();
        for(int i = head[u];~i;i=e[i].next){
            int v = e[i].v , w = e[i].w;
            if(w > 0 && lv[v] < 0) lv[v] = lv[u] + 1,que.push(v);
        }
    }
}
int dfs(int u ,int t , int f){
    if(u==t) return f;
    int used = 0 , w;
    for(int i=head[u];~i;i=e[i].next){
        int v = e[i].v; int w = e[i].w;
        if(lv[v] == lv[u]+1&&w > 0){
            int d = dfs(v , t , min(f,w));
            if(d > 0){
                e[i].w -= f; e[i^1].w += f;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s , int t){
    int flow = 0;
    for(;;){
        bfs(s);
        if(lv[t]<0) return flow;
        int f;
        while((f = dfs(s , t , inf))>0){
            flow += f;
        }
    }
    return flow;
}
int main()
{
   init();
   scanf("%d%d%d",&r,&c,&d);
   char ch[30];
   for(int i=1;i<=r;i++)
    for(int j = 1; j <= c;j++)
    mark[i][j] = ++cnt;
    int sum = 0;
   for(int i=1;i<=r;i++)
   {
       scanf("%s",ch+1);
       for(int j=1;j<=c;j++)
           mp[i][j] = ch[j] - 0;
   }
   for(int i = 1; i <= r;i++)
   {
       scanf("%s",ch+1);
       for(int j = 1; j <= c;j++)
       if(ch[j] == L)
       {
           sum++;
           Insert(0 , mark[i][j] , 1);
       }
   }
   build();
   printf("%d\n",sum - max_flow(0 , 801));
}
View Code

 

bzoj 1066(网络流)