• bzoj1001--最大流转最短路


    http://www.lydsy.com/JudgeOnline/problem.php?id=1001

    思路:这应该算是经典的最大流求最小割吧。不过题目中n,m<=1000,用最大流会TLE,所以要利用平面图的一些性质。

    这里讲一下平面图的对偶图性质。

    在平面图中,所有边将图分成了n个平面。我们将平面标号,对于原图中的每条边,在与之相邻的两个平面间连一条边,最后得到的图就是原图的对偶图。

    对偶图有如下性质:

    1、对偶图的边数与原图相等。

    2、对偶图中的每个环对应原图中的割。

    于是可以在原图中的s和t间再连一条边,得到对偶图,用spfa求一次最短路就是答案。

    具体可以参考http://wenku.baidu.com/link?url=87F10nBWauMdSF-PaKHoG-3fZj0jFE63P6pHSeX6ZiguQqXOQxm41iLWW5IdZCp2MWFQ8JghamfeI68PtLqEv_JSWapGp5z415gNoYb031u

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    #define INF 1000000000
    struct edge{
        int p,to;
        edge(int p=0,int to=0):p(p),to(to){};
    };
    vector<edge>g[5000000];
    queue<int>q;
    int i,j,k,n,m,s,t,x,y,d[5000000];
    void spfa(){
        for(int i=2;i<=t;i++)d[i]=INF;
        q.push(1);
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                edge e=g[x][i];
                if(d[x]+e.p<d[e.to]){
                    d[e.to]=d[x]+e.p;
                    q.push(e.to);
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        if(n==1){
            int minn=INF;
            for(i=1;i<m;i++){
                scanf("%d",&x);
                minn=min(minn,x);
            }
            printf("%d
    ",minn);
            return 0;
        }else if(m==1){
            int minn=INF;
            for(i=1;i<n;i++){
                scanf("%d",&x);
                minn=min(minn,x);
            }
            printf("%d
    ",minn);
            return 0;
        }
        t=(n-1)*(m-1)*2+2;
        for(i=1;i<=n;i++)
        for(j=1;j<m;j++){
            scanf("%d",&k);
            x=(i-2)*(m-1)*2+j*2;
            y=(i-1)*(m-1)*2+j*2+1;
            if(i==1)x=1;else if(i==n)y=t;
            g[x].push_back(edge(k,y));
            g[y].push_back(edge(k,x));
        }
        for(i=1;i<n;i++)
        for(j=1;j<=m;j++){
            scanf("%d",&k);
            x=(i-1)*(m-1)*2+j*2-1;
            y=x+1;
            if(j==1)x=t;else if(j==m)y=1;
            g[x].push_back(edge(k,y));
            g[y].push_back(edge(k,x));
        }
        for(i=1;i<n;i++)
        for(j=1;j<m;j++){
            scanf("%d",&k);
            x=(i-1)*(m-1)*2+j*2;
            y=x+1;
            g[x].push_back(edge(k,y));
            g[y].push_back(edge(k,x));
        }
        spfa();
        printf("%d
    ",d[t]);
        return 0;
    }
  • 相关阅读:
    win10笔记本实现双屏显示的自如切换
    word-如何将文字设置为插入超链接
    opencv-python教程学习系列13-图像平滑
    第12课 经典问题解析一
    第11课 新型的类型转换
    第10课 C++中的新成员
    第9课 函数重载分析(下)
    第8课 函数重载分析(上)
    第7课 函数参数的扩展
    第6课 内联函数分析
  • 原文地址:https://www.cnblogs.com/gjghfd/p/5866444.html
Copyright © 2020-2023  润新知