• P4001-[ICPC-Beijing 2006]狼抓兔子【对偶图】


    正题

    题目链接:https://www.luogu.com.cn/problem/P4001


    题目大意

    给出一个类似于
    graph
    的网格图,求起点到终点的最小割。


    解题思路

    最小割直接跑网络流,然后发现(dinic)都过不了。(好像加点玄学优化就能过)

    然后上点科技,平面图最小割转其补图(对偶图)的最短路

    • 平面图:满足所有边不相交的情况下可以被画在平面上的一张图(G(V,E))
    • 对偶图:将一张平面图的各个区域变成一个点,然后平面图上分割两个区域(a,b)的边在对偶图上就是连接(a,b)的一条边。

    这题显然是平面图,转换成对偶图就是
    在这里插入图片描述
    画的比较丑,将就着看把。

    然后感性理解一下发现结论确实成立。

    (dij)就好了

    时间复杂度(O(nmlog (nm)))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define mp(x,y) make_pair(x,y)
    using namespace std;
    const int N=1010*1010*2;
    struct node{
        int to,next,w;
    }a[N<<4];
    int n,m,s,t,tot,ls[N],f[N];
    bool v[N];
    priority_queue<pair<int ,int > >q;
    int p(int x,int y,int z)
    {return ((x-1)*m+y)*2-z;}
    void addl(int x,int y,int w){
        a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;
        a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=w;
        return;
    }
    int dij(){
        memset(f,0x3f,sizeof(f));
        f[s]=0;q.push(mp(0,s));
        while(!q.empty()){
            int x=q.top().second;q.pop();
            if(v[x])continue;v[x]=1;
            for(int i=ls[x];i;i=a[i].next){
                int y=a[i].to;
                if(f[x]+a[i].w<f[y]){
                    f[y]=f[x]+a[i].w;
                    q.push(mp(-f[y],y));
                }
            }
        }
        return f[t];
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        s=p(n-1,m-1,0)+1;t=s+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<m;j++){
                int x;scanf("%d",&x);
                if(i==1)addl(s,p(i,j,0),x);
                else if(i==n)addl(p(i-1,j,1),t,x);
                else addl(p(i-1,j,1),p(i,j,0),x);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<=m;j++){
                int x;scanf("%d",&x);
                if(j==1)addl(p(i,j,1),t,x);
                else if(j==m)addl(s,p(i,j-1,0),x);
                else addl(p(i,j,1),p(i,j-1,0),x);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<m;j++){
                int x;scanf("%d",&x);
                addl(p(i,j,0),p(i,j,1),x);
            }
        printf("%d
    ",dij());
        return 0;
    }
    
  • 相关阅读:
    angular 复选框回选
    $parse
    AngularJS 指令的 Scope (作用域)
    文献解读 (1)
    献给初学者:常用的细胞凋亡检测方法
    KofamKOALA
    Dfam.h5.gz下载
    Augustus-3.3.3安装
    bamtools 2.5.1安装
    R语言从原点开始作图
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14324156.html
Copyright © 2020-2023  润新知