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\n",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\n",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\n",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\n",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\n",sum);
 }
    return 0;
}





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值