BZOJ2007 NOI2010 海拔 网络流+最短路

题意:给定一个N*N的网格,每个格点均与周围的八个点连边,每条边有一个边权,求安排每个点的点权h,使$\sum\limits_{e \in G} {e.w \times \min \{ ({h_{e.u}} - {h_{e.v}}),0\} }$最小

题解:所有高度一定不是0就是1,而且一定有一条线使得这条线一边是0,另一边是1。显然最小割。然后这是个平面图,Dijkstra随便跑。

#include <queue>
#include <functional>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=500+2;
const int MAXM=6000000+2;
struct HASH{
    int u,w;
    HASH *next;
    HASH(){}
    HASH(int _u,int _w,HASH *_next):u(_u),w(_w),next(_next){}
}*table[MAXM],mem[MAXM];
struct EDGE{
    int u,w;
    EDGE(){}
    EDGE(int _u,int _w):u(_u),w(_w){}
    bool friend operator<(EDGE a,EDGE b){ a.w>a.w;}
};
int N,cnt,g[MAXN][MAXN],d[MAXM];
priority_queue<EDGE> q;

void Insert(int u,int v,int w){ table[u]=&(mem[cnt++]=HASH(v,w,table[u]));}

int Dijkstra(int s,int t){
    memset(d,0X7F,sizeof(d));
    d[s]=0,q.push(EDGE(s,0));

    int x;
    while(!q.empty()){
        x=q.top().u,q.pop();
        for(HASH *p=table[x];p;p=p->next)
            if(d[p->u]>d[x]+p->w){
                d[p->u]=d[x]+p->w;
                q.push(EDGE(p->u,d[p->u]));
            }
    }
    return d[t];
}

int main(){
    cin >> N;
    cnt=1;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
            g[i][j]=++cnt;
    for(int i=1;i<=N;i++) g[i][0]=g[N+1][i]=1;

    cnt=0;
    for(int i=1,w;i<=N+1;i++)
        for(int j=1;j<=N;j++){
            cin >> w;
            Insert(g[i-1][j],g[i][j],w);
        }
    for(int i=1,w;i<=N;i++)
        for(int j=1;j<=N+1;j++){
            cin >> w;
            Insert(g[i][j],g[i][j-1],w);
        }
    for(int i=1,w;i<=N+1;i++)
        for(int j=1;j<=N;j++){
            cin >> w;
            Insert(g[i][j],g[i-1][j],w);
        }
    for(int i=1,w;i<=N;i++)
        for(int j=1;j<=N+1;j++){
            cin >> w;
            Insert(g[i][j-1],g[i][j],w);
        }

    cout << Dijkstra(0,1) << endl;

    return 0;
}
View Code

 

posted @ 2017-02-28 22:27  WDZRMPCBIT  阅读(127)  评论(0编辑  收藏  举报