BOJ 17835 면접보는 승범이네
출처 : https://www.acmicpc.net/problem/17835
아 이거 사실 증명 안하고 예전에 풀었던거 비슷하게 감으로 떄려 맞췄다.
그래서 정당성에 대한 설명은 못하겠고 풀이방법만 적을게.(누가 증명좀 ㅎ)
- 역방향 그래프를 만든다.
- 출발지는 면접장 전체다. -> pq, memo에 면접장 전부 반영해준다.
- 다익스트라를 돌린다.
- 그럼 memo[i]가 가장 큰게 문제에서 원하는 두번째 답dl다.
- 첫번째 답은 돌골렘 대가리도 유추할수 있을것이다.
추가)
면접장과 모두 거리가 0인 간선으로 연결된 노드를 하나 만든 다음 해당 노드에서 다익스트라를 돌린다고 생각하면 memo[i]에 나온 결과는 임의의 면접장에서 i번 도시까지 가는 가장 짧은 거리가 된다. (새로만든노드 -> 면접장은 거리가 0이므로.) 위의 방법은 이와 동일.
-by lovinix
아래는 코드(사실상 니들은 100line 이후는 볼 필요 없다. 다익스트라 로직보다 pq 구현이 더 김. 이래서 내가 다익스트라 문제 풀기 싫음)
아 그리고 입력을 잘보자 후..... long long써야 된다.....
또 방문체크 안하면? tle ㅋ
#include<stdio.h>
#include<malloc.h>
struct e
{
int num;
long long cost;
};
struct e* elist[100010], heap[500050];
int answer, eindex[100010], vn, en, k, start[100010], hidx, v[100010];
long long memo[100010];
void input();
void pb(int, int, long long);
void di();
void push(int, long long);
struct e pop();
int get_mode(int);
struct e calc();
void fin();
void make_answer();
int main(void)
{
make_answer();
return 0;
}
void make_answer()
{
struct e ret;
input();
di();
ret = calc();
fin();
printf("%d\n", ret.num);
printf("%lld\n", ret.cost);
}
void input()
{
int a, b;
long long c;
scanf("%d %d %d", &vn, &en, &k);
while (en--)
{
scanf("%d %d %lld", &a, &b, &c);
pb(b, a, c);
}
for (a = 0; a < k; a++)
{
scanf("%d", &start[a]);
}
for (a = 1; a <= vn; a++)
{
memo[a] = 0x7fffffffffffffff;
}
}
void di()
{
int d, next;
long long ncost;
struct e pnode;
for (d = 0; d < k; d++)
{
push(start[d], 0);
memo[start[d]] = 0;
}
while (hidx)
{
pnode = pop();
if (v[pnode.num])
{
continue;
}
for (d = 0; d < eindex[pnode.num]; d++)
{
next = elist[pnode.num][d].num;
ncost = elist[pnode.num][d].cost;
if (memo[next] > memo[pnode.num] + ncost)
{
memo[next] = memo[pnode.num] + ncost;
push(next, memo[next]);
}
}
v[pnode.num] = 1;
}
}
struct e calc()
{
int num, d;
long long cost;
struct e ret;
for (d = 1, num = 111111, cost = -1; d <= vn; d++)
{
if (cost < memo[d])
{
cost = memo[d];
num = d;
}
}
ret.cost = cost;
ret.num = num;
return ret;
}
void pb(int a, int b, long long c)
{
elist[a] = (struct e*)realloc(elist[a], sizeof(struct e) * (eindex[a] + 1));
elist[a][eindex[a]].num = b;
elist[a][eindex[a]++].cost = c;
}
void fin()
{
int i;
for (i = 0; i <= vn; i++)
{
if (elist[i])
{
free(elist[i]);
}
}
}
void push(int num, long long cost)
{
int cidx, tidx;
struct e temp;
hidx++;
heap[hidx].cost = cost;
heap[hidx].num = num;
cidx = hidx;
tidx = cidx / 2;
while (!(!tidx || heap[tidx].cost < heap[cidx].cost))
{
temp = heap[cidx];
heap[cidx] = heap[tidx];
heap[tidx] = temp;
cidx = tidx;
tidx = cidx / 2;
}
}
struct e pop()
{
int cidx, mode;
struct e ret, left, temp, right;
ret = heap[1];
heap[1] = heap[hidx];
hidx--;
cidx = 1;
while (1)
{
mode = get_mode(cidx);
if (!mode)
{
break;
}
else if (mode == 1)
{
left = heap[cidx * 2];
if (left.cost < heap[cidx].cost)
{
temp = heap[cidx];
heap[cidx] = heap[cidx * 2];
heap[cidx * 2] = temp;
cidx *= 2;
}
else
{
break;
}
}
else
{
left = heap[cidx * 2];
right = heap[cidx * 2 + 1];
if (left.cost < right.cost)
{
if (left.cost < heap[cidx].cost)
{
temp = heap[cidx];
heap[cidx] = heap[cidx * 2];
heap[cidx * 2] = temp;
cidx *= 2;
}
else
{
break;
}
}
else
{
if (right.cost < heap[cidx].cost)
{
temp = heap[cidx];
heap[cidx] = heap[cidx * 2 + 1];
heap[cidx * 2 + 1] = temp;
cidx *= 2;
cidx++;
}
else
{
break;
}
}
}
}
return ret;
}
int get_mode(int idx)
{
if (idx * 2 + 1 <= hidx)
{
return 2;
}
if (idx * 2 == hidx)
{
return 1;
}
return 0;
}