-
Notifications
You must be signed in to change notification settings - Fork 0
/
byteland.c
324 lines (278 loc) · 8.6 KB
/
byteland.c
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*
*
* @file Byteland.c
* @brief Solving a graph theory problem using C
* @author Matthieu Crepeau
* @version 1.01
* @date 09/16/2013
*
* @todo
*
*
*/
#include <stdio.h>
#include <stdlib.h>
// Used to define the use of assertion and debugging messages depending on the compilation options
#ifdef DEBUG
#define ASSERT_PERROR(assertion) if (!(assertion)) \
printf("Error in file %s, line %d : " #assertion "@n", __FILE__, __LINE__), exit(10)
#define DEBUG_PRINTF \
printf
#define DEBUG_PRINTGRAPH \
printGraph
#else
#define ASSERT_PERROR(assertion)
#define DEBUG_PRINTF(format, args...) ((void)0)
#define DEBUG_PRINTGRAPH(graph)
#endif
// Structure to represent an adjacency list node
struct AdjListNode
{
int dest;
struct AdjListNode* next;
};
// Structure to represent an adjacency list
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
int Ci; // cost of destroying the city
char army; // army protecting the city (either A or B)
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be N (number of cities, or vertices, in graph)
struct Graph
{
int N;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest)
{
struct AdjListNode* newNode = (struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int N)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->N = N;
// Create an array of adjacency lists. Size of array will be N
graph->array = (struct AdjList*) malloc(N * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
int i;
for (i = 0; i < N; ++i)
graph->array[i].head = NULL;
graph->array[i].Ci = 0;
graph->array[i].army = ' ';
return graph;
}
void removeElement(struct Graph* graph, int n, int i)
{
struct AdjListNode *temp, *prev;
struct AdjListNode *head = graph->array[i].head;
temp=head;
while(temp!=NULL)
{
if(temp->dest==n)
{
if(temp==head) //If node is first node
{
if(head->next == NULL)
{
graph->array[i].head = NULL;
}
else
{
head->dest = temp->next->dest; //Copy the data of the next node to head
head->next = temp->next->next; //Remove the link of the next node
}
return;
}
else
{
prev->next=temp->next; // Remove node from Linked List
return;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return;
}
void deleteNode(struct Graph* graph, int n)
{
int i;
if (graph->array[n].head == NULL && graph->array[n].army == ' ' && graph->array[n].Ci == 0){
DEBUG_PRINTF("Error : node %d has already been deleted !\n\n", n);
return;
}
else
{
graph->array[n].head = NULL;
graph->array[n].army = ' ';
graph->array[n].Ci = 0;
}
// Deletes element in the linked lists
for (i=0;i<graph->N;++i)
{
removeElement(graph, n, i);
}
}
void setNodeProperty(struct Graph* graph, int n, int Ci, char army){
graph->array[n].Ci = Ci;
graph->array[n].army = army;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// A utility function to print the adjacency list representation of graph
void printGraph(struct Graph* graph)
{
int n;
for (n = 0; n < graph->N; ++n)
{
struct AdjListNode* pCrawl = graph->array[n].head;
if (graph->array[n].army != ' ')
{
printf("\n Adjacency list of city %d, protected by army %c of cost %d ->", n, graph->array[n].army, graph->array[n].Ci);
while (pCrawl)
{
printf(" %d", pCrawl->dest);
pCrawl = pCrawl->next;
}
}
printf("\n");
}
}
void executeTestCase(struct Graph* graph)
{
int i, n;
int nbs_cities_protected[graph->N], nb_cities_protected, total_nb_cities_protected;
int costs_cities_protected[graph->N];
float cost_ratios[graph->N], cost_ratio;
int city, cost = 0;
DEBUG_PRINTF("\n Cities linked to other cities protected by a different army :\n\n");
//Run the city selection algorithm
do
{
total_nb_cities_protected = 0; // Reinitializes the overall number of cities linked && protected by two different armies
// Scans the array looking for links to cities protected by an opposite army
for (n = 0; n < graph->N; ++n)
{
struct AdjListNode* pCrawl = graph->array[n].head;
nbs_cities_protected[n] = 0; // Reinitializes the number of cities linked && protected by two different armies for this node
costs_cities_protected[n] = 0;
if (graph->array[n].army != ' ')
{
DEBUG_PRINTF(" %d |", n);
while (pCrawl)
{
if (graph->array[n].army != graph->array[pCrawl->dest].army)
{
DEBUG_PRINTF(" %d ", pCrawl->dest);
nbs_cities_protected[n]++; // Increments the number of cities linked && protected by two different armies for this node
costs_cities_protected[n] += graph->array[pCrawl->dest].Ci;
}
pCrawl = pCrawl->next;
}
if (nbs_cities_protected[n] > 0) cost_ratios[n]= (float) (graph->array[n].Ci)/(nbs_cities_protected[n]);
total_nb_cities_protected+=nbs_cities_protected[n];
}
DEBUG_PRINTF("\n");
}
for(i=0;i<n;++i) // We scan the array of nbs_cities_protected
{
if (nbs_cities_protected[i] > 0 && graph->array[i].Ci <= costs_cities_protected[i]) // When we find the first value that's above 0
{
cost_ratio = cost_ratios[i]; // We store it in another variable
nb_cities_protected = nbs_cities_protected[i];
city = i;
for(i++;i<n;++i) // We scan the rest of the array, starting where we left off
{
if (nbs_cities_protected[i] > 0 && graph->array[i].Ci <= costs_cities_protected[i])
{
if (nbs_cities_protected[i] == nb_cities_protected) // The other variable is used to compare the rest of the array
{
if (cost_ratios[i] < cost_ratio)
{
cost_ratio = cost_ratios[i];
nb_cities_protected = nbs_cities_protected[i];
city = i;
}
}
if (nbs_cities_protected[i] > nb_cities_protected) // The other variable is used to compare the rest of the array
{
cost_ratio = cost_ratios[i];
nb_cities_protected = nbs_cities_protected[i];
city = i;
}
}
}
cost += graph->array[city].Ci; //Add the cost
//Delete the city
DEBUG_PRINTF("\n ->Deletion of node %d<- \n\n", city);
deleteNode(graph, city);
}
}
}while(total_nb_cities_protected != 0);
DEBUG_PRINTF("\nTotal cost : ");
printf("%d\n", cost);
}
// Driver program
int main(void)
{
char *line = NULL;
size_t size;
int i, j;
int nb_test_cases, N, M, Ci;
char army[2];
int city1, city2;
struct Graph* graph;
if (getline(&line, &size, stdin) == -1) DEBUG_PRINTF("No line\n");
else {
sscanf(line,"%d", &nb_test_cases);
DEBUG_PRINTF("There are %d test cases\n", nb_test_cases);
}
for(i=0;i<nb_test_cases;i++){
if (getline(&line, &size, stdin) == -1) DEBUG_PRINTF("No line\n");
else {
sscanf(line,"%d %d", &N, &M);
}
graph = createGraph(N);
DEBUG_PRINTF("\nTest case %d : Byteland has %d cities and %d roads\n", i+1, N, M);
for(j=0;j<N;j++){
if (getline(&line, &size, stdin) == -1) DEBUG_PRINTF("No line\n");
else {
sscanf(line,"%c %d", army, &Ci);
//DEBUG_PRINTF("%s %d\n", army, Ci);
setNodeProperty(graph, j, Ci, army[0]);
}
}
for(j=0;j<M;j++){
if (getline(&line, &size, stdin) == -1) printf("No line\n");
else {
sscanf(line,"%d %d", &city1, &city2);
//DEBUG_PRINTF("%d %d\n", city1, city2);
addEdge(graph, city1-1, city2-1);
}
}
DEBUG_PRINTGRAPH(graph);
executeTestCase(graph);
}
return 0;
}