• 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
    ",sum - max_flow(0 , 801));
    }
    View Code
  • 相关阅读:
    2015年 Stoi&Gdoi 反思总结与未来计划
    bzoj4517: [Sdoi2016]排列计数--数学+拓展欧几里得
    bzoj4518: [Sdoi2016]征途--斜率DP
    BZOJ 1391: [Ceoi2008]order
    BZOJ 2527: [Poi2011]Meteors
    BZOJ 2087: [Poi2010]Sheep
    BZOJ 1283: 序列
    BZOJ 1914: [Usaco2010 OPen]Triangle Counting 数三角形
    BZOJ 3513: [MUTC2013]idiots
    BZOJ 3771: Triple
  • 原文地址:https://www.cnblogs.com/rtyfcvb/p/6891928.html
Copyright © 2020-2023  润新知