zoukankan      html  css  js  c++  java
  • HDOJ:1533-Going Home(最小费用流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533


    解题心得:

    • 第一次写最小费用流的题,去hdoj上找了一个入门级题目,建图比较简单,用了spfa和Dij两种写法。

    //spfa
    #include <bits/stdc++.h> using namespace std; const int maxn = 110*110; struct edge{ int to, cap, dis, rev; edge(int To, int Cap, int Dis, int Rev): to(To), cap(Cap), dis(Dis), rev(Rev) {} }; //感觉这里写得超级智障,懒得改了 struct men { int x,y; }; struct House { int x,y; }; vector <edge> ve[maxn]; vector <men> man; vector <House> house; int n, m, S, T; char maps[maxn][maxn]; void init() { S = 0; man.clear(); house.clear(); for(int i=0;i<maxn;i++) ve[i].clear(); for(int i=1;i<=n;i++) scanf("%s",maps[i]+1); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(maps[i][j] == 'm') { men now; now.x = i; now.y = j; man.push_back(now); } else if(maps[i][j] == 'H') { House temp; temp.x = i; temp.y = j; house.push_back(temp); } } } T = man.size() + house.size() + 1; } void build_adge(int s, int to, int dis) { ve[s].push_back(edge(to, 1, dis, ve[to].size())); ve[to].push_back(edge(s, 0, -dis, ve[s].size()-1)); } void add_adge() { for(int i=0;i<man.size();i++) { build_adge(S, i+1, 0); for(int j=0;j<house.size();j++) { int dis = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y); build_adge(i+1, man.size()+j+1, dis); } } for(int i=0;i<house.size();i++) { build_adge(i+1+man.size(), T, 0); } } int dist[maxn], preve[maxn], prevv[maxn]; bool vis[maxn]; bool SPFA() { memset(preve, 0, sizeof(preve)); memset(vis, 0, sizeof(vis)); memset(prevv, 0, sizeof(prevv)); memset(dist, 0x3f, sizeof(dist)); dist[S] = 0; queue <int> qu; qu.push(S); while(!qu.empty()) { int now = qu.front() ;qu.pop(); vis[now] = false; for(int i=0;i<ve[now].size();i++) { edge &e = ve[now][i]; if(dist[e.to] > dist[now] + e.dis && e.cap > 0) { dist[e.to] = dist[now] + e.dis; prevv[e.to] = now; preve[e.to] = i; if(!vis[e.to]) { qu.push(e.to); vis[e.to] = true; } } } } return dist[T] != 0x3f3f3f3f; } int min_cost_flow() { int ans = 0; while(SPFA()) { for(int v = T; v!=S ; v =prevv[v]) { edge &e = ve[prevv[v]][preve[v]]; e.cap -= 1; ve[v][e.rev].cap += 1; ans += e.dis; } } return ans; } int main() { while(scanf("%d%d",&n,&m) && n+m) { init(); add_adge(); printf("%d ",min_cost_flow()); } return 0; }

    Dij

    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> P;
    const int maxn = 110*110;
    
    struct edge{
        int to, cap, dis, rev;
    
        edge(int To, int Cap, int Dis, int Rev):
                to(To), cap(Cap), dis(Dis), rev(Rev) {}
    };
    
    struct men {
        int x,y;
    };
    
    struct House {
        int x,y;
    };
    
    vector <edge> ve[maxn];
    vector <men> man;
    vector <House> house;
    int n, m, S, T, h[maxn];
    char maps[maxn][maxn];
    
    
    void init() {
        S = 0;
        man.clear();
        house.clear();
        memset(h, 0, sizeof(h));
        for(int i=0;i<maxn;i++)
            ve[i].clear();
        for(int i=1;i<=n;i++)
            scanf("%s",maps[i]+1);
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                if(maps[i][j] == 'm') {
                    men now;
                    now.x = i;
                    now.y = j;
                    man.push_back(now);
                } else if(maps[i][j] == 'H') {
                    House temp;
                    temp.x = i;
                    temp.y = j;
                    house.push_back(temp);
                }
            }
        }
        T = man.size() + house.size() + 1;
    }
    
    void build_adge(int s, int to, int dis) {
        ve[s].push_back(edge(to, 1, dis, ve[to].size()));
        ve[to].push_back(edge(s, 0, -dis, ve[s].size()-1));
    }
    
    void add_adge() {
        for(int i=0;i<man.size();i++) {
            build_adge(S, i+1, 0);
            for(int j=0;j<house.size();j++) {
                int dis = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y);
                build_adge(i+1, man.size()+j+1, dis);
            }
        }
        for(int i=0;i<house.size();i++) {
            build_adge(i+1+man.size(), T, 0);
        }
    }
    
    int dist[maxn], preve[maxn], prevv[maxn];
    bool Dij() {
        memset(preve, 0, sizeof(preve));
        memset(prevv, 0, sizeof(prevv));
        memset(dist, 0x3f, sizeof(dist));
        dist[S] = 0;
        priority_queue <P, vector<P>, greater<P> > qu;
        qu.push(make_pair(0,0));
        while(!qu.empty()) {
            P now = qu.top(); qu.pop();
            int pos = now.second;
            if(dist[pos] < now.first)
                continue;
            for(int i=0;i<ve[pos].size();i++) {
                edge &e = ve[pos][i];
                if(e.cap > 0 && dist[e.to] > dist[pos] + e.dis + h[pos] - h[e.to]) {
                    dist[e.to] = dist[pos] + e.dis + h[pos] - h[e.to];
                    prevv[e.to] = pos;
                    preve[e.to] = i;
                    qu.push(make_pair(dist[e.to], e.to));
                }
            }
        }
        return dist[T] != 0x3f3f3f3f;
    }
    
    int min_cost_flow() {
        int ans = 0;
        while(Dij()) {
            for(int i=0;i<=T;i++)
                h[i] += dist[i];
            ans += h[T];
            for(int v = T; v!=S ; v =prevv[v]) {
                edge &e = ve[prevv[v]][preve[v]];
                e.cap -= 1;
                ve[v][e.rev].cap += 1;
            }
        }
        return ans;
    }
    
    int main() {
        while(scanf("%d%d",&n,&m) && n+m) {
            init();
            add_adge();
            printf("%d
    ",min_cost_flow());
        }
        return 0;
    }
  • 相关阅读:
    美国航天局的十大编码戒律(转)
    大型数据库应用解决方案总结
    IOCP模型
    SSH 连接慢的解决方案详解
    指针(详解)【转】
    有关推挽输出、开漏输出、复用开漏输出、复用推挽输出以及上拉输入、下拉输入、浮空输入、模拟输入区别【转】
    USB入门开发的八个问题&USB枚举『转』
    浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)
    KEIL Code RO-data RW-data ZI-data 【转】
    262K Color
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9501245.html
Copyright © 2011-2022 走看看