BZOJ1001狼抓兔子

昨天在BZOJ上看到了一道题,就是问题集的第二道 BZOJ1001
题目描述是这样的:
这里写图片描述
当时第一眼看过去就知道这道题是求最小割的问题,但是怎么样求出最小割?
去网上直接搜这道题的解析,发现有一种解法很巧妙,就是求出这张图的对偶图,是在输入数据的时候就直接根据循环的层数建出对偶图了(这里的对偶图做了一下处理,要连接start和end)
这个是芜湖一中的周冬同学ppt上的图,我直接借来用了
然后对对偶图做djkstra算法,以建的对偶图中的s*和t* 中的某一点为起点,找出最小最优路径,便是最小割这里贴出一份一位同学的代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define inf 0x7fffffff
using namespace std;
const int maxn=2000000+10;
const int M = maxn*3+10;

int n,m,nn,mm;
int from,to;
struct Edge
{
    int v,flow;
    int next;
}edge[M];
int head[maxn],edgenum;

void add(int u,int v,int flow)
{
    edge[edgenum].v=v ;edge[edgenum].flow=flow ;
    edge[edgenum].next=head[u] ;head[u]=edgenum++ ;

    edge[edgenum].v=u ;edge[edgenum].flow=flow ;
    edge[edgenum].next=head[v] ;head[v]=edgenum++ ;
}

struct node
{
    int v,w;
    friend bool operator < (node a,node b)
    {
        return a.w > b.w;
    }
}cur,tail;
int d[maxn],vis[maxn];
void Dijkstra(int from,int to)
{
    for (int i=0 ;i<maxn ;i++) d[i]=inf;
    memset(vis,0,sizeof(vis));
    d[from]=0;
    priority_queue<node> Q;
    cur.v=from ;cur.w=0 ;
    Q.push(cur);
    while (!Q.empty())
    {
        cur=Q.top() ;Q.pop() ;
        int x=cur.v;
        if (vis[x]) continue;
        vis[x]=1;
        for (int i=head[x] ;i!=-1 ;i=edge[i].next)
        {
            if (d[edge[i].v ]>d[x]+edge[i].flow)
            {
                d[edge[i].v ]=d[x]+edge[i].flow;
                tail.v=edge[i].v;
                tail.w=d[edge[i].v ];
                Q.push(tail);
            }
        }
    }
    printf("%d\n",d[to]);
}

int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        memset(head,-1,sizeof(head));
        edgenum=0;
        from=0;
        to=2*(n-1)*(m-1)+1;
        int x,y,cost;
        for (int i=1 ;i<=n ;i++)
        {
            for (int j=1 ;j<m ;j++)
            {
                scanf("%d",&cost);
                x= i==1 ? from : (2*(i-1)-1)*(m-1)+j;
                y= i==n ? to : (2*(i-1))*(m-1)+j;
                add(x,y,cost);
            }
        }
        for (int i=1 ;i<n ;i++)
        {
            for (int j=1 ;j<=m ;j++)
            {
                scanf("%d",&cost);
                x= j==1 ? to : (2*(i-1))*(m-1)+j-1;
                y= j==m ? from : (2*(i-1))*(m-1)+j-1+m;
                add(x,y,cost);
            }
        }
        for (int i=1 ;i<n ;i++)
        {
            for (int j=1 ;j<m ;j++)
            {
                scanf("%d",&cost);
                x=(2*(i-1))*(m-1)+j;
                y=(2*(i-1)+1)*(m-1)+j;
                add(x,y,cost);
            }
        }
        Dijkstra(from,to);
    }
    return 0;
}

这个同学建图的方法很简单灵活,我记得大二的时候我数据结构课程的助教就是这样建图的,首先建一个边集,一个head数组,head[n]代表编号为n的点的第一个边在边集中的位置,边集中存储了所有的边,边结构体中用到的next就是指针指向下一条边在边集中的位置。
读数据的时候先是读横向的边
这个时候如果是第一行的话,起点就是s*,如果是最后一行,起点就是t* 其余的根据i和j的值计算出位置
而后就是用djkstra算法求出最终结果。

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、付费专栏及课程。

余额充值