zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    hdu 1251 字典树模板题 ---多串 查找单词出现次数
    一个极其简洁的Python网页抓取程序,自己主动从雅虎財经抓取股票数据
    JSONObject与JSONArray的使用
    关于DPM(Deformable Part Model)算法中模型结构的解释
    fullcalendar日历控件知识点集合
    android--自己定义ProgressDialog显示位置(其他Dialog子类都能够设置)
    最简单的Java框架
    java final keyword
    IBinder对象在进程间传递的形式(一)
    windows的定时任务设置
  • 原文地址:https://www.cnblogs.com/gjghfd/p/5866444.html
Copyright © 2011-2022 走看看