본문 바로가기
[C++] 알고리즘 교육/20.그래프알고리즘

[알고리즘 20.1.3] 그래프 - 파티

by 안산학생 2019. 8. 12.

문제


철수네 마을에는 N개의 집이 있으며, 각 집은 고유한 번호를 부여받는다. 각 번호는 1보다 크거나 같고, N보다 작거나 같다. 철수는 마을 K에 살고 있다. 집과 집 사이에는 단방향 도로가 존재하기 때문에, 이 도로를 통하여 서로 이동할 수 있다. 즉, N개의 마을은 그래프 구조를 이룬다. 편의상 각 집에는 한 사람만이 살고 있다고 가정하자. 크리스마스인 오늘, 철수는 본인의 집에서 파티를 열려고 한다. 따라서 다른 모든 사람들이 철수의 집에 모여 파티를 즐기고, 파티가 끝난 후에는 다시 본인의 집으로 돌아가려 한다. 사람들은 본인의 집에서 철수네 집까지 이동하기 위하여 항상 최단거리로 이동하기를 원하고, 마찬가지로 철수네 집에서 본인의 집에 갈 때도 최단거리로 이동하기를 원한다. 집의 개수와 두 집을 잇는 단방향 도로의 정보, 그리고 철수의 집 번호가 주어질 때, 마을 사람들이 파티를 즐기기 위해서 이동해야 하는 총 거리의 합을 출력하는 프로그램을 작성하시오.

 

입력


첫째 줄에 정점의 개수 N과 간선의 개수 M, 그리고 철수의 집 번호 K가 주어진다. ( 1 ≤ N, K ≤ 1,000, 1 ≤ M ≤ 100,000 ) 둘째 줄부터 간선의 정보가 주어진다. 각 줄은 두 개의 숫자 a, b, c로 이루어져 있으며, 이는 정점 a에서 정점 b로 이동하는 데 시간이 c만큼 걸린다는 의미이다. 양방향 도로가 아님에 주의하자.

 

출력


마을 사람들이 파티를 즐기기 위해서 이동해야 하는 총 거리의 합을 출력한다.

 

예제 입력

6 10 3

1 2 1

2 5 2

3 1 5

3 2 3

3 4 1

3 6 4

4 1 1

5 3 1

6 5 3

6 4 2

예제 출력

32

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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
138
139
140
141
142
143
144
145
146
147
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
const int MAX = 100005;
 
vector <int> graph[MAX];
vector <int> cost[MAX];
 
int table[MAX];
bool check[MAX]; //check[i] = true 라면 i는 최단거리가 확정되었다.
 
//reverse
vector <int> reverseGraph[MAX];
vector <int> reverseCost[MAX];
 
int reverseTable[MAX];
bool reverseCheck[MAX];
 
int n, m, k;
 
 
void inNode(int node){
    for(int i=0; i<=n; i++){
      table[i] = 987987987;
      check[i] = 0;
    }
    table[node] = 0;
}
 
void inNodeRe(int node){
  for(int i=0; i<=n; i++){
    reverseTable[i] = 987987987;
    reverseCheck[i] = 0;
  }
  reverseTable[node] = 0;
}
 
void distance(){
  for(int i=0; i<=n; i++){
    // (1) 최솟값을 구한다. 단, 지금까지 최단거리로 확정되지 않았던 노드에 대해서.
    // (2) 그 최솟값을 갖는 노드로부터 뻗어나간다.
    int minValue = 987987987, minIndex = -1;
 
    for(int j=0; j<=n; j++){
      if(!check[j] && minValue > table[j]){
        minValue = table[j];
        minIndex = j;
      }
    }
 
    check[minIndex] = true;
    
    for(int j=0; j<graph[minIndex].size(); j++){
      int node2 = graph[minIndex][j];
      int cost2 = cost[minIndex][j];
      
      if(table[node2] > table[minIndex] + cost2){
        table[node2] = table[minIndex]+cost2;
      }
    }
  }
}
 
void distanceRe(){
   for(int i=0; i<=n; i++){
    int minValue = 987987987, minIndex = -1;
 
    for(int j=0; j<=n; j++){
      if(!reverseCheck[j] && minValue > reverseTable[j]){
        minValue = reverseTable[j];
        minIndex = j;
      }
    }
 
    reverseCheck[minIndex] = true;
    
    for(int j=0; j<reverseGraph[minIndex].size(); j++){
      int node2 = reverseGraph[minIndex][j];
      int cost2 = reverseCost[minIndex][j];
      
      if(reverseTable[node2] > reverseTable[minIndex] + cost2){
        reverseTable[node2] = reverseTable[minIndex]+cost2;
      }
    }
  }
}
 
int main(){
  cin>>n>>k>>m;
 
  int a,b,c;
  for(int i=0; i<k; i++){
    cin>>a>>b>>c;
    graph[a].push_back(b);
    cost[a].push_back(c);
    
    reverseGraph[b].push_back(a);
    reverseCost[b].push_back(c);
  }
 
  inNode(m);
  distance();
  
  //철수네 집 -> 각자 집
  int sum=0;
  for(int i=1; i<=n; i++){
    sum+=table[i];
  }
  
  inNodeRe(m);
  distanceRe();
 
  //각자 집 -> 철수네 집
  for(int i=1; i<=n; i++){
    sum+=reverseTable[i];
  }
  
  
  printf("%d\n", sum);
  return 0;
}
 
//예제입력
/*
8 11 0 6
0 1 3
0 5 1
1 2 4
1 3 1
1 5 1
2 4 6
2 6 9
2 7 4
3 4 2
4 6 9
6 7 3
*/
 
 
 
 
 
 
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

댓글