BZOJ1001

开坑!

1001: [BeiJing2006]狼抓兔子

思路:平面图最小割
Orz周冬,主要思想都在他的文章《浅析最大最小定理在信息学竞赛中的应用》中提到

显然最大流不现实
将整个图从斜线切开,分为两块
若我们将每一块区域看成一个点,两块区域的公共边作为这两点的连边
显然,从左下到右上的最短路就是整个图的最小割
真是神思想!

代码:
我这个人比较喜欢手写优先队列……

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define rint register int
#define ull unsigned long long
using namespace std;
const int MAXN=2*1000*1000+10,MAXM=6*1000*1000+10;
int n,m;
int s,t;
#define heng(a,b) ((a-1)*2-(1-b))*(m-1)
#define inf 1<<30
int frontx[MAXM],fronty[MAXM],frontk[MAXM];
int stdx[MAXN],orderx[MAXM];
int nn,mm;
void add(int x,int y,int k)
{
    if (x!=t) { frontx[++mm]=x; fronty[mm]=y; frontk[mm]=k; }
    if (y!=s) { frontx[++mm]=y; fronty[mm]=x; frontk[mm]=k; }
    return ;
}
int num[MAXN];
void Read(int &k)
{
    char c=getchar(); k=0;
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9') {
        k=k*10+c-'0';
        c=getchar(); }
    return ;
}
void sortx()
{
    for (rint i=1;i<=mm;i++)
        num[frontx[i]]++;
    for (rint i=1;i<=nn;i++) {
        num[i]+=num[i-1];
        stdx[i]=num[i]; }
    for (rint i=1;i<=mm;i++)
        orderx[++num[frontx[i]-1]]=i;
    return ;
}
struct Heap
{
    unsigned int dis;
    int x;
}heap[MAXN];
bool operator < (Heap A,Heap B) { return A.dis<B.dis; }
int point[MAXN];
void adjustup(int x)
{
    static bool next;
    next=true;
    while (next) {
        next=false;
        static int f;
        f=x/2;
        if (f)
            if (heap[x]<heap[f]) {
                swap(heap[x],heap[f]);
                point[heap[x].x]=x; point[heap[f].x]=f;
                x=f; next=true; }}
    return ;
}
void change(int l,int r)
{
    swap(heap[l],heap[r]);
    point[heap[r].x]=r; point[heap[l].x]=l;
    return ;
}
void adjustdown(int x)
{
    static bool next;
    next=true;
    while (next) {
        next=false; 
        static int l,r;
        l=x*2,r=x*2+1;
        if (l<=nn)
            if (r<=nn) {
                if (heap[l]<heap[r] && heap[l]<heap[x]) {
                    change(l,x);
                    x=l; next=true; }
                else if (heap[r]<heap[x]) {
                    change(r,x);
                    x=r; next=true; }
            else if (heap[l]<heap[x]) {
                change(l,x);
                x=l; next=true; }}}
    return ;
}
void dijsktra()
{
    for (rint i=1;i<=nn;i++) {
        heap[i].dis=inf;
        point[i]=heap[i].x=i; }
    heap[s].dis=0;
    adjustup(s);
    while (nn) {
        static Heap now;
        now=heap[1];
        if (now.x==t) {
            cout<<heap[point[t]].dis<<endl;
            return ; }
        change(1,nn);
        nn--; adjustdown(1);
        static int x;
        x=now.x;
        for (rint i=stdx[x-1]+1;i<=stdx[x];i++) {
            static int next;
            next=fronty[orderx[i]];
            if (heap[point[next]].dis>now.dis+frontk[orderx[i]]) {
                heap[point[next]].dis=now.dis+frontk[orderx[i]];
                adjustup(point[next]); }}}
    return ;
}
void init()
{
    Read(n); Read(m);
    if (n==1 || m==1) {
        int nn=n,ans=inf;
        if (nn==1) nn=m;
        for (int k,i=1;i<nn;i++) {
            Read(k);
            ans=min(ans,k); }
        if (ans==inf)
            cout<<0<<endl;
        else
            cout<<ans<<endl;
        return ; }
    s=(n-1)*(m-1)*2+1,t=(n-1)*(m-1)*2+2;
    nn=t;
    for (rint i=1;i<=n;i++)
        for (rint k,j=1;j<m;j++) {
            Read(k);
            if (i==1) add(s,heng(i,1)+j,k);
            else if (i==n) add(heng(i,0)+j,t,k);
            else add(heng(i,0)+j,heng(i,1)+j,k); }
    for (rint i=1;i<n;i++)
        for (rint k,j=1;j<=m;j++) {
            Read(k);
            if (j==1) add(t,heng(i+1,0)+j,k);
            else if (j==m) add(s,heng(i,1)+j-1,k);
            else add(heng(i,1)+j-1,heng(i+1,0)+j,k); }
    for (rint i=1;i<n;i++)
        for (rint k,j=1;j<m;j++) {
            Read(k);
            add(heng(i,1)+j,heng(i+1,0)+j,k); }
    sortx();
    dijsktra();
    return ;
}
int main()
{
    init();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值