BZOJ 1001 [BeiJing2006]狼抓兔子

平面图最小割转对偶图最短路。

第一眼看到这题,显然是最小割嘛。。。根据最大流最小割定理,跑一遍最大流即可,但复杂度 O(n2m) ,显然要T啊。

然后我就学习了平面图最小割转对偶图最短路的想法,看完就会做了,资料传送门:两极相通——浅析最大最小定理在信息学竞赛中的应用

注意,对偶图最短路做法只使用于s-t平面图,不一定适用于一般图

这里顺便摘抄一些平面图的重要定义和性质,详细内容看资料:

·平面图:若图G可画在平面上,使得任意两条边都不会在非端点处相交,则称图G是平面图。

·s-t平面图:平面图中的一个点为源点s,另外一个点为汇点t,且s和t都在图中的无界面的边界上,这样的平面图称为s-t平面图

·欧拉公式:如果一个连通的平面图有n个点,m条边,f个域(面),那么f=m-n+2

·性质:每个平面图G都有一个与其对偶的平面图G*

话说这题用SPFA慢出翔了,推荐堆优化dijkstra(复杂度 O((n+m)log2n)

#include<cstdio>
#include<queue>
#include<cstring>
#define add2(u,v,w) add(u,v,w);add(v,u,w)
#define N 1005
using namespace std;
int in()
{
    int r=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')r=r*10+ch-'0',ch=getchar();
    return r;
}
queue<int> q;
bool vis[2200000];
int last[2200000], d[2200000], s=0, t=1, cnt=0;
int pack(int x, int y, int side){return (x*1001+y)+side*1002005;}
struct edge{int next,to,v;}e[2*3*N*N];
void add(int a, int b, int w)
{
    e[++cnt]=(edge){last[a],b,w};
    last[a]=cnt;
}
struct node
{
    int id, v;
    node(){}
    node(int a, int b):id(a),v(b){}
    bool operator < (const node &a) const
    {
        return a.v<v;
    }
};
int dijkstra()
{
    priority_queue<node> q;
    memset(d,63,sizeof(d));
    q.push(node(s,d[s]=0));
    vis[s]=1;
    while(!q.empty())
    {
        int x=q.top().id;
        q.pop();
        vis[x]=1;
        if(x==t)break;
        for(int i = last[x]; i; i=e[i].next)
        {
            int y=e[i].to;
            if(!vis[y]&&d[x]+e[i].v<d[y])
            {
                d[y]=d[x]+e[i].v;
                q.push(node(y,d[y]));
            }
        }
    }
    return d[t];
}
int main()
{
    int n, m, len;
    n=in();m=in();
    if(n==1&&m==1)return !printf("0\n");
    for(int i = 1; i <= n; i++)
        for(int j = 1; j < m; j++)
        {
            len=in();
            add2(pack(i,j,1),pack(i-1,j,0),len);
        }
    for(int i = 1; i < n; i++)
        for(int j = 1; j <= m; j++)
        {
            len=in();
            add2(pack(i,j,0),pack(i,j-1,1),len);
        }
    for(int i = 1; i < n; i++)
        for(int j = 1; j < m; j++)
        {
            len=in();
            add2(pack(i,j,0),pack(i,j,1),len);
        }
    for(int j = 1; j <= m; j++)
    {
        add(pack(0,j,0),t,0);
        add(s,pack(n,j,1),0);
    }
    for(int i = 1; i <= n; i++)
    {
        add(pack(i,m,0),t,0);
        add(s,pack(i,0,1),0);
    }
    int ans=dijkstra();
    printf("%d\n",ans);
}
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 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值