poj3068(最小费用流)

(和poj2135很像很像,就多了一个情况而已,基础入门题)
题目大概意思为总共有N个仓库,求两条不同路径从起点到达终点,若是没有两条,打出Not possible,若是有可能打出所需最小费用

很简单把每个边容量设为1,费用则为题目所给,然后把起点和终点之间连一个很大很大的值,若是不足两条,费用就会变得很大很大,很容易判断出来,然后套最小费用流模板即可

(按题目所说的话,不仅边不能相同,点也不能相同,但可能样例比较松,不考虑点不重复也能过,如果想严谨的话,可以把一个点分为两个点来看,之间连一条容量为1,费用为0的边即可)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define INF 1000000005
using namespace std;
struct edge
{
    int to, cap, coust, rev;
    edge(int t, int c, int s, int r)
    {
        to = t; cap = c; coust = s; rev = r;
    }
};
vector<struct edge> data[105];
int dist[105];
int N, M;
void add_edg(int i, int j, int k)
{
    data[i].push_back(edge(j, 1, k, data[j].size()));
    data[j].push_back(edge(i, 0, -k, data[i].size() - 1));
}
int min_coust(int from, int to, int flow)
{
    int money = 0;
    int prev[105];
    int prep[105];
    while(flow--)
    {
        fill(dist, dist + N, INF);
        dist[0] = 0;
        bool flag = true;
        while(flag)
        {
            flag = false;
            for(int i = 0; i < N; i++)
            {
                if(dist[i] != INF)
                {
                    for(int j = 0; j < data[i].size(); j++)
                    {
                        struct edge e = data[i][j];
                        if(e.cap != 0 && dist[i] + e.coust < dist[e.to])
                        {
                            flag = true;
                            dist[e.to] = dist[i] + e.coust;
                            prev[e.to] = i;
                            prep[e.to] = j;
                        }
                    }
                }
            }
        }
        for(int i = to; i != from; i = prev[i])
        {
            data[prev[i]][prep[i]].cap--;
            data[i][data[prev[i]][prep[i]].rev].cap++;
        }
        money = money + dist[to];
    }
    return money;
}
int main()
{
    int f = 1;
    while(1)
    {
        int a, b, c;
        scanf("%d %d", &N, &M);
        if(N == 0 && M == 0)
        {
            break;
        }
        for(int i = 0; i < N; i++)
        {
            data[i].clear();
        }
        for(int i = 0; i < M; i++)
        {
            scanf("%d %d %d", &a, &b, &c);
            add_edg(a, b, c);
        }
        data[0].push_back(edge(N - 1, INF, INF, data[N - 1].size()));
        data[N-1].push_back(edge(0, 0, -INF, data[0].size() - 1));
        int d = min_coust(0, N - 1, 2);
        if(d >= INF)
        {
            printf("Instance #%d: Not possible\n", f);
        }
        else
        {
            printf("Instance #%d: %d\n", f, d);
        }
        f++;
    }

}
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值