반응형

문제 출처 :


https://www.acmicpc.net/problem/11405



알고리즘 분석 :


문제 해결에 필요한 사항

1. MCMF

2. 그래프 모델링


Source-서점-사람-Sink로 그래프 모델링을 준비한다.


1. 사람과 Sink를 연결한다. 이때 capacity는 입력받는 값으로 이용된다.(사람이 사고싶어하는 책의 개수를 의미)


2. Source와 서점을 연결한다. 이때 capacity는 입력받는 값으로 이용된다.(서점에서 가지고 있는 책의 개수를 의미)


3. 서점과 사람을 연결한다. 이때 cost는 입력받는 값을 이용하고 capacity = INF로 둔다.(어짜피 S-서점, 사람-T에서 결정나게 된다.)


이제 MCMF를 이용하면 결과를 구할 수 있다.






소스 코드 : 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
 
using namespace std;
 
const int INF = 987654321;
const int MAX_V = 300;
const int S = MAX_V - 2;
const int T = MAX_V - 1;
 
struct Edge {
    int v, cost, capacity, flow, rev;
    Edge(int v, int cost, int c, int f, int rev)
        :v(v), cost(cost), capacity(c), flow(f), rev(rev) {}
};
 
vector<Edge> adj[MAX_V];
 
void addEdge(int here, int next, int cost, int cap)
{
    adj[here].emplace_back(next, cost, cap, 0, adj[next].size());
    adj[next].emplace_back(here, -cost, 00, adj[here].size() - 1);
}
 
int main()
{
    int n, m;
    scanf("%d %d"&n, &m);
 
    // 사람
    for (int j = 1; j <= n; j++)
    {
        int cap;
        scanf("%d"&cap);
 
        addEdge(j + m, T, 0, cap);
    }
 
    // 서점
    for (int i = 1; i <= m; i++)
    {
        int cap;
        scanf("%d"&cap);
 
        addEdge(S, i, 0, cap);
    }
 
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            int cost;
            scanf("%d"&cost);
 
            addEdge(i, j + m, cost, INF);
        }
    }
 
    int result = 0;
 
    while (1)
    {
        int vPrev[MAX_V], ePrev[MAX_V], dist[MAX_V];
        bool inQ[MAX_V] = { };
 
        queue<int> q;
        fill(vPrev, vPrev + MAX_V, -1);
        fill(ePrev, ePrev + MAX_V, -1);
        fill(dist, dist + MAX_V, INF);
 
        dist[S] = 0;
        inQ[S] = true;
 
        q.push(S);
 
        while (!q.empty())
        {
            int here = q.front();
            q.pop();
 
            inQ[here] = false;
 
            for (int i = 0; i < adj[here].size(); i++)
            {
                int next = adj[here][i].v;
                int c = adj[here][i].capacity;
                int f = adj[here][i].flow;
                int d = adj[here][i].cost;
 
                if (c - f > && dist[next] > dist[here] + d)
                {
                    dist[next] = dist[here] + d;
                    vPrev[next] = here;
                    ePrev[next] = i;
 
                    if (!inQ[next])
                    {
                        q.push(next);
                        inQ[next] = true;
                    }
                }
            }
        }
        if (vPrev[T] == -1)
            break;
 
        int flow = INF;
 
        for (int i = T; i != S; i = vPrev[i])
        {
            int prev = vPrev[i];
            int idx = ePrev[i];
            flow = min(flow, adj[prev][idx].capacity - adj[prev][idx].flow);
        }
 
        for (int i = T; i != S; i = vPrev[i])
        {
            int prev = vPrev[i];
            int idx = ePrev[i];
 
            result += adj[prev][idx].cost * flow;
 
            adj[prev][idx].flow += flow;
            adj[i][adj[prev][idx].rev].flow -= flow;
 
        }
    }
    printf("%d\n", result);
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[8992번] 집기 게임  (0) 2017.12.07
[1544번] 사이클 단어  (0) 2017.12.07
[3980번] 선발 명단  (0) 2017.12.06
[11409번] 열혈강호 6  (0) 2017.12.05
[7154번] Job Postings  (0) 2017.12.05