zoukankan      html  css  js  c++  java
  • bzoj1001狼抓兔子

    Description

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

     

    左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 
    1:(x,y)<==>(x+1,y) 
    2:(x,y)<==>(x,y+1) 
    3:(x,y)<==>(x+1,y+1) 
    道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
    开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
    这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
    才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
    狼的数量要最小。因为狼还要去找喜羊羊麻烦.

    Input

    第一行为N,M.表示网格的大小,N,M均小于等于1000.
    接下来分三部分
    第一部分共N行,每行M-1个数,表示横向道路的权值. 
    第二部分共N-1行,每行M个数,表示纵向道路的权值. 
    第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 
    输入文件保证不超过10M

    Output

    输出一个整数,表示参与伏击的狼的最小数量.

    Sample Input

    3 4
    5 6 4
    4 3 1
    7 5 3
    5 6 7 8
    8 7 6 5
    5 5 5
    6 6 6

    Sample Output

    14

    最小割等于最大流

    感觉还是比较好写的

    dinic算法

    误把反向边和反向弧弄混

    调了很久。。。。。。

    感谢师兄大佬的指导微笑

    em......

    某位大佬牛逼啊

    想到把反向边和反向弧建在一起

    瞬间快了1000多ms

    强啊微笑

    #include<cstdio>  
    #include<iostream>  
    #include<cstring>  
    const int M=3*1000*1000+5,N=1000*1000+100;  
    struct node  
    {  
        int to,next,v;  
    }e[M*4];  
    int first[N],cnt=1,t;  
    int deep[N],qu[N];    
    int cur[N]; 
    void insert(int u,int v,int q)  
    {
          e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].v=q;  
    }     
    int read()   
    {  
        char t=getchar();  
        int ans=0;  
        while(t<'0'||t>'9')   t=getchar ();  
        while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();  
        return ans;  
    }  
    bool bfs()  
    {  
        memset(deep,-1,sizeof(deep));  
        deep[1]=0;  
        int i=1,j=2;  
        qu[1]=1;  
        while(i!=j)  
        {  
            int r=qu[i++];if(i==N)  i=1;  
            for(int k=first[r];k;k=e[k].next)  
            if(deep[e[k].to]==-1&&e[k].v)  
            {  
                deep[e[k].to]=deep[r]+1;  
                qu[j++]=e[k].to;if(j==N)    j=1;      
            }  
        }  
        if(deep[t]==-1) return 0;  
        return 1;  
    }  
    int dfs(int x,int a)  
    {  
        if(x==t||a==0)  return a;  
        int flow=0,t;  
        for(int& k=cur[x];k;k=e[k].next)  
            if(deep[e[k].to]==deep[x]+1&&e[k].v)  
            {  
                t=dfs(e[k].to,std::min(a,e[k].v));  
                e[k].v-=t;e[k^1].v+=t;  
                flow+=t;a-=t;  
                if(!a)  break;  
            }  
        if(!flow)   deep[x]=-1;  
        return flow;  
    }  
    int main()  
    {  
        int h=read(),l=read(),q;  
        for(int i=1;i<=h;i++)  
            for(int j=1;j<l;j++)  
            {  
                q=read();  
                //反向边  
                insert((i-1)*l+j,(i-1)*l+j+1,q);  
                insert((i-1)*l+j+1,(i-1)*l+j,q);  
            }  
            for(int i=1;i<h;i++)  
            for(int j=1;j<=l;j++)  
            {  
                 q=read();  
                insert((i-1)*l+j,i*l+j,q);  
                insert(i*l+j,(i-1)*l+j,q);  
            }  
            for(int i=1;i<h;i++)  
            for(int j=1;j<l;j++)  
            {  
                 q=read();  
                insert((i-1)*l+j,i*l+j+1,q);  
                insert(i*l+j+1,(i-1)*l+j,q);  
            }  
            t=h*l;  
            int ans=0;  
            while(bfs())  
            {  
                for(int i=1;i<=t;i++)
                cur[i]=first[i];
                ans+=dfs(1,1e8);  
            }  
            printf("%d
    ",ans);  
            return 0;  
    }  

    spfa  周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》

    利用最短路求最小割

    #include<cstdio>
    const int N=2*1e6+15,M=3*1e6+15;
    struct node
    {
        int to,v,next;
    }e[M*2];
    int cnt=0;
    int first[N];
    int qu[N],book[N],dis[N];
    void insert(int u,int v,int q)
    {
        e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].v=q;
        e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;e[cnt].v=q;
    //    printf("%d %d %d
    ",u,v,q);
    }
    int read()
    {
        int ans=0;
        char t=getchar();
        while(t>'9'||t<'0')   t=getchar();
        while(t<='9'&&t>='0') ans=ans*10+t-'0',t=getchar();
        return ans;
    }
    void spfa(int t)
    {
        int i=1,j=2;
        dis[0]=0;
        for(int i=1;i<=t;i++)    dis[i]=1e8;
        qu[1]=0;book[0]=1;
        while(i!=j)
        {
            int r=qu[i++];book[r]=0;if(i==N)	i=0;	
            for(int k=first[r];k;k=e[k].next)
            {
                if(dis[e[k].to]>dis[r]+e[k].v)
                {
                    dis[e[k].to]=dis[r]+e[k].v;
    //              printf("%d to%d ==%d
    ",r,e[k].to,dis[e[k].to]);
                    if(!book[e[k].to])
                    {
                    	if(dis[e[k].to]<dis[qu[i]])//slf优化
                    	{
                    		i--;
                    		if(i<0)	i=N-2;
    						qu[i]=e[k].to;
                    	}
    					else qu[j++]=e[k].to; 
    					if(j==N)	j=0;
                        book[e[k].to]=1;
                    }
                }
            }		
        }
        printf("%d
    ",dis[t]);
    }
    int main()
    {
        int h=read(),l=read(),q;
        int s=0,t=(l-1)*2*(h-1)+1;
        if(h!=1&&l!=1)
        {
        for(int i=1;i<=h;i++)
        for(int j=1;j<l;j++)
        {
            q=read();
            if(i==1)    insert((i-1)*2*(l-1)+j*2,s,q);
            else if(i==h)       insert(t,(i-2)*2*(l-1)+j*2-1,q);
            else    insert((i-1)*2*(l-1)+j*2,(i-2)*2*(l-1)+j*2-1,q);
        }
          
          
        for(int i=1;i<h;i++)
        for(int j=1;j<=l;j++)
        {
             q=read();
            if(j==1)    insert(t,(i-1)*2*(l-1)+(j-1)*2+1,q);
            else if(j==l)   insert(s,(i-1)*2*(l-1)+(j-1)*2,q);
            else    insert((i-1)*2*(l-1)+(j-1)*2+1,(i-1)*2*(l-1)+(j-1)*2,q);
        }
          
        for(int i=1;i<h;i++)
        for(int j=1;j<l;j++)
        {
             q=read();
            insert((i-1)*2*(l-1)+(j-1)*2+1,(i-1)*2*(l-1)+(j-1)*2+2,q);
        }
          
        spfa(t);
     }
     else
     {
        int sum=1e8;
            for(int i=1;i<=h;i++)
        for(int j=1;j<l;j++)
        {
             q=read();
            sum=sum<q?sum:q;
        }
        for(int i=1;i<h;i++)
        for(int j=1;j<=l;j++)
        {
            q=read();
           sum=sum<q?sum:q;
        }
        printf("%d
    ",sum);
     }
        return 0;
    }
    
    
    
    
    
    
    
    
    
    
    
       
    
  • 相关阅读:
    postgresql 在linux下导出数据
    第一次linux下安装nginx记录
    第一次搭建redis集群
    手动mvn install指令向maven本地仓库安装jar包
    windows10下Kafka环境搭建
    在win10环境下搭建 solr 开发环境
    git 常用命令
    生成文件夹的树结构信息
    List集合和JSON互转工具类
    Cmd命令 查看端口被占用
  • 原文地址:https://www.cnblogs.com/Brian551/p/7353046.html
Copyright © 2011-2022 走看看