nkoj p3000 【nodgd造水题】嵩嵩

nkoj p3000 【nodgd造水题】嵩嵩

问题描述

受何老板之托,嵩嵩在美国为何老板采购的若干吨货物。这批货物已通过水路运送到了我国某沿海城市,现在需要通过公路将这些货物运送到何老板家。嵩嵩的地图上有N(2 <= N <= 200) 座城市,编号1到N,嵩嵩在1号城市,何老板的家在N号城市。这N座城市间有P(1 <= P <= 40,000) 条双向通行的道路相连,每条道路长度不超过1,000,000。两座城市间可能有多条道路相连。
嵩嵩雇了T(1 <= T <= 200)辆卡车运送这批货物。为了避免被人发现或引起别人的注意,嵩嵩安排这T辆车选择不同的道路行驶,也就是同一条道路不会被走两次。
请帮助嵩嵩安排这T辆车的线路,使得走过的总长度尽量短。
嵩嵩向你保证在不走重复道路的情况下,一定能够把T车货物运到目的地。
注意:题目中描述的“道路”相当于图论中的“边”。
注:题目改编自NKOJ1605。其实是nodgd做1605的时候一开始读错题了,但是既然代码都写好了,总不能浪费了吧,所以就有了这道题!

输入格式

第一行包括三个空格间隔的整数N,P,T。
接下来P行,每行有三个空格间隔的整数A,B,C。表示城市A、B间有条长度为C的道路。

输出格式

一整数,表示经过的道路总长度的最小值。

样例输入

7 9 2
1 2 2
2 3 5
3 7 5
1 4 1
4 3 1
4 5 7
5 7 1
1 6 3
6 7 3

样例输出

13

一点小想法

费用流模板题,把 1 看成原点 n 看成汇点,每条路的费用就是它的长度,每条路的容量为 1
只需要注意一点就是只有 t 辆货车,所以当最大流达到 t 时退出找增广路,输出此时的最小费用。

代码

#include 
#include 
#include 
#include 
using namespace std;
const int Max = (40000 + 5) << 3;
int Last[Max];
struct Eg {
    int Next, Child, Cost, Cap;
} egs[Max];
int n, p, t;
void addegs(int num, int fr, int to, int c, int v) {
    egs[num].Child = to;
    egs[num].Cap = c;
    egs[num].Cost = v;
    egs[num].Next = Last[fr];
    Last[fr] = num;
}
int dis[Max], maxflow, mincost, flow[Max], pre[Max], head[Max];
bool vis[Max];
queue<int> q;
bool spfa(int s, int t) {
    memset(dis, 127 / 2, sizeof(dis));
    memset(flow, 127 / 2, sizeof(flow));
    q.push(s);
    dis[s] = 0;
    vis[s] = true;
    pre[t] = -1;
    while(q.size()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = Last[u]; i; i = egs[i].Next) {
            int v = egs[i].Child;
            if(egs[i].Cap && dis[v] > dis[u] + egs[i].Cost) {
                dis[v] = dis[u] + egs[i].Cost;
                pre[v] = u;
                head[v] = i;
                flow[v] = min(flow[u], egs[i].Cap);
                if(!vis[v]) {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    return pre[t] != -1;
}
int s, T;
void mcmf() {
    while(spfa(1, T) && maxflow < t) {
        int u = T;
        maxflow += flow[T];
        mincost += flow[T] * dis[T];
        while(u != s) {
            egs[head[u]].Cap -= flow[T];
            egs[head[u] ^ 1].Cap += flow[T];
            u = pre[u];
        }
    }
}

int main() {
    scanf("%d %d %d", &n, &p, &t);
    int num = 2;
    for(int i = 1; i <= p; i++) {
        int fr, to, c;
        scanf("%d %d %d", &fr, &to, &c);
        addegs(num++, fr, to, 1, c);
        addegs(num++, to, fr, 0, -c);
        addegs(num++, to, fr, 1, c);
        addegs(num++, fr, to, 0, -c);
    }
    s = 1;
    T = n;
    mcmf();
    printf("%d", mincost);
    return 0;
}

你可能感兴趣的:(竞赛技巧)