aoj 2226 Merry Christmas

Merry Christmas

Time Limit : 8 sec, Memory Limit : 65536 KB

Problem J: Merry Christmas

International Christmas Present Company (ICPC) is a company to employ Santa and deliver presents on Christmas. Many parents request ICPC to deliver presents to their children at specified time of December 24. Although same Santa can deliver two or more presents, because it takes time to move between houses, two or more Santa might be needed to finish all the requests on time.

Employing Santa needs much money, so the president of ICPC employed you, a great program- mer, to optimize delivery schedule. Your task is to write a program to calculate the minimum number of Santa necessary to finish the given requests on time. Because each Santa has been well trained and can conceal himself in the town, you can put the initial position of each Santa anywhere.

Input

The input consists of several datasets. Each dataset is formatted as follows.

N M L
uvd1
uvd2
.
.
.
uM vM dM
pt1
pt2
.
.
.
pL tL

The first line of a dataset contains three integer, N , M and L (1 ≤ N ≤ 100, 0 ≤ M ≤ 1000, 1 ≤ L ≤ 1000) each indicates the number of houses, roads and requests respectively.

The following M lines describe the road network. The i-th line contains three integers, ui , vi , and di (0 ≤ ui < vi≤ N - 1, 1 ≤ di ≤ 100) which means that there is a road connecting houses ui and vi with di length. Each road is bidirectional. There is at most one road between same pair of houses. Whole network might be disconnected.

The next L lines describe the requests. The i-th line contains two integers, pi and ti (0 ≤ pi ≤ N - 1, 0 ≤ ti ≤ 108 ) which means that there is a delivery request to house pi on time ti . There is at most one request for same place and time. You can assume that time taken other than movement can be neglectable, and every Santa has the same speed, one unit distance per unit time.

The end of the input is indicated by a line containing three zeros separated by a space, and you should not process this as a test case.

Output

Print the minimum number of Santa necessary to finish all the requests on time.

Sample Input

3 2 3
0 1 10
1 2 10
0 0
1 10
2 0
3 2 4
0 1 10
1 2 10
0 0
1 10
2 20
0 40
10 10 10
0 1 39
2 3 48
3 5 20
4 8 43
3 9 10
8 9 40
3 4 5
5 7 20
1 7 93
1 3 20
0 0
1 100000000
2 100
3 543
4 500
5 400
6 300
7 200
8 100
9 100
0 0 0

Output for the Sample Input

2
1
4

 题意:有L个货物需要圣诞老人派送,每个货物要送到谁家,并且几点之前送掉都有严格规定。准时送完全部的L个货物至少需要多少个圣诞老人。

思路:一开始我们考虑最坏的情况,即L个货物需要L个圣诞老人才能全部送完,之后再进行优化,找找是否可以少用圣诞来人。如果一个圣诞老人送完一个货物后有足够时间走到另外一个货物的送货地点,那么这两个货物可以由这一个圣诞老人一起送,这样就能少用一个圣诞老人。把所有能够一起送的两个货物之间都连上边,图的最大匹配即为能减少的圣诞老人个数x,L-x就是最少所需圣诞老人数。例如如下情况二分图:
                                     即为货物1送完可直接送货物2;货物2送完可直接送货物3;货物4送完可直接送货物5,货物5送完可直接送货物3,其最大匹配为3,那么一共可以节省3个圣诞老人。

代码:

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
#define INF 0x3f3f3f3f
const int N_MAX = 2000 + 100, V_MAX = 2000 + 100;
int V;//点的个数
vector<int>G[N_MAX];
int match[N_MAX];
bool used[N_MAX];
void add_edge(int u, int v) {
    G[u].push_back(v);
    G[v].push_back(u);
}

bool dfs(int v) {
    used[v] = true;
    for (int i = 0; i < G[v].size(); i++) {
        int u = G[v][i], w = match[u];
        if (w < 0 || !used[w] && dfs(w)) {
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}

int bipartite_matching() {
    int res = 0;
    memset(match, -1, sizeof(match));
    for (int v = 0; v < V; v++) {
        if (match[v] < 0) {
            memset(used, 0, sizeof(used));
            if (dfs(v))
                res++;
        }
    }
    return res;
}
int N, M, L, dis[N_MAX][N_MAX];
int p[N_MAX], t[N_MAX];
int main() {

    while (scanf("%d%d%d", &N, &M, &L) && N) {
        V = 2 * L;
        memset(dis, INF, sizeof(dis));
        for (int i = 0; i < M; i++) {
            int u, v, d;
            scanf("%d%d%d", &u, &v, &d);
            dis[u][v] = d;
            dis[v][u] = d;
        }
        for (int i = 0; i < L; i++) {
            scanf("%d%d", p + i, t + i);
        }
        //floyd
        for (int k = 0; k < N; k++) {
            dis[k][k] = 0;//!!!!!!!!
            for (int i = 0; i < N; i++)
                for (int j = 0; j < N; j++) {
                    dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
                }
        }
        /////
        for (int i = 0; i < L; i++) {
            for (int j = 0; j < L; j++) {
                if (i != j&&t[i] + dis[p[i]][p[j]] <= t[j]) {//可以从p[i]走到p[j]送货,少用一个人
                    add_edge( i, L+j);//连一条边,连边的两端货物可以让一个人送即可
                }
            }
        }
        printf("%d
", L - bipartite_matching());
        for (int i = 0; i < V; i++)
            G[i].clear();
    }

    return 0;
}
原文地址:https://www.cnblogs.com/ZefengYao/p/7270089.html