Dijkstra,平面图最大流(动物园大逃亡,LA 3661)

学会了用最短路求平面图的最大流。


http://blog.sina.com.cn/s/blog_60707c0f01011fnn.html


代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll maxn = 2e6;
const ll inf = 0x3f3f3f3f;

struct Edge
{
    ll from,to,dist;
};

struct HeapNode
{
    ll d,u;
    bool operator < (const HeapNode& rhs) const
    {
        return d>rhs.d;
    }
};

struct Dijkstra
{
    ll n,m;
    vector<Edge>edges;
    vector<ll>G[maxn];
    ll d[maxn],done[maxn];
    void init(ll n)
    {
        this->n=n;
        rep(i,0,n-1) G[i].clear();
        edges.clear();
    }
    void add(ll u,ll v,ll d)
    {
        edges.push_back((Edge){u,v,d});
        edges.push_back((Edge){v,u,d});
        m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }
    void dijkstra(ll s)
    {
        rep(i,0,n-1)
        {
            d[i]=inf;
            done[i]=0;
        }
        d[s]=0;
        priority_queue<HeapNode>Q;
        Q.push((HeapNode){0,s});
        while(!Q.empty())
        {
            HeapNode x=Q.top();Q.pop();
            ll u=x.u;
            if(done[u]) continue;
            done[u]=1;
            ll sz=G[u].size();
            rep(i,0,sz-1)
            {
                Edge& e=edges[G[u][i]];
                if(d[e.to]>d[e.from]+e.dist)
                {
                    d[e.to]=d[e.from]+e.dist;
                    Q.push((HeapNode){d[e.to],e.to});
                }
            }
        }
    }
};

ll n,m;
ll tp;
Dijkstra DIJ;
ll kase;

ll id(ll i,ll j,ll k)
{
    return 2*(i*(m-1)+j)+k;
}

int main()
{
    while(scanf("%lld %lld",&n,&m)==2&&n&&m)
    {
        DIJ.init((n-1)*(m-1)*2+2);
        ll s=(n-1)*(m-1)*2;
        ll t=(n-1)*(m-1)*2+1;

        rep(i,0,n-1) rep(j,0,m-2)
        {
            scanf("%lld",&tp);
            if(i==0) DIJ.add(id(i,j,1),t,tp);
            else if(i==n-1) DIJ.add(s,id(i-1,j,0),tp);
            else DIJ.add(id(i,j,1),id(i-1,j,0),tp);
        }

        rep(i,0,n-2) rep(j,0,m-1)
        {
            scanf("%lld",&tp);
            if(j==0) DIJ.add(s,id(i,j,0),tp);
            else if(j==m-1) DIJ.add(id(i,j-1,1),t,tp);
            else DIJ.add(id(i,j-1,1),id(i,j,0),tp);
        }

        rep(i,0,n-2) rep(j,0,m-2)
        {
            scanf("%lld",&tp);
            DIJ.add(id(i,j,0),id(i,j,1),tp);
        }

        DIJ.dijkstra(s);
        printf("Case %lld: Minimum = %lld\n",++kase,DIJ.d[t]);
    }
    return 0;
}