2016년 4월 6일 수요일

1613 - 역사

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

입력으로 주어지는 사건들의 관계를 방향그래프로 생각하면 사건 A와 사건 C 사이에 A->B->C 의 순서가 되는 사건 B가 있으면, 사건 C는 사건 A 이후에 발생했다는 사실을 알 수 있다.

플로이드 와샬을 통해 각 사건들의 관계를 모두 구하면 s줄에 걸친 물음에 대답할 수 있다.


#include <cstdio>

bool v[401][401];

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    while(m--){
        int s, e;
        scanf("%d %d", &s, &e);
        v[s][e] = true;
    }
    for(int k=1; k<=n; ++k){
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=n; ++j){
                v[i][j] |= v[i][k] & v[k][j];
            }
        }
    }
 
    scanf("%d", &m);
    while(m--){
        int s, e;
        scanf("%d %d", &s, &e);
        if(v[s][e]) puts("-1");
        else if(v[e][s]) puts("1");
        else puts("0");
    }
    return 0;
}

댓글 2개:

Unknown :

안녕하세요
저도 이 문제 시도 했었는데요.
저또한 Floyd알고리즘을 사용했는데 시간 초과로 실패합니다. 계속 채점중에 4%에서 멈춰 있다가 시간 초과로 죽는데, 전혀 모르겠습니다. 혹시 한번 봐 주실수 있나요?
#include
#include

using namespace std;

int n, k;
int map[401][401], ck[401];

void init() {
int go = 0, to = 0;
scanf("%d", &n);
scanf("%d", &k);

for (int i = 0; i < k; i++) {
scanf("%d%d", &go, &to);
map[go][to] = 1;
}
}

void makeMap() {
for (int x = 1; x <= n; x++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
map[i][j] = (map[i][x] & map[x][j]);
}
}
}
}

void result() {
int m = 0;
int x = 0, y = 0;

scanf("%d", &m);

for (int i = 0; i < m; i++) {
scanf("%d%d", &x, &y);

if (map[x][y] == 1) {
cout << "-1" << endl;
}
else if (map[y][x] == 1) {
cout << "1" << endl;
}
else{
cout << "0" << endl;
}
}
}

int main() {
init();
makeMap();
result();

return 0;
}

Joona Yoon :

댓글 감사합니다.
우선, map[i][j] = (map[i][x] & map[x][j]); 가 아니라 map[i][j] |= (map[i][x] & map[x][j]); 입니다.
대입 연산이 아닌 OR 중첩연산을 하셔야합니다. (이미 연결된 길은 연결된 상태로 유지해야하기 때문이죠)

그리고 만약 위 소스가 시간초과를 받으신다면 cout<<"1"<<endl 이 아니라 puts("1") 이나 printf("1\n") 을 사용하시는걸 추천합니다.
cout과 endl은 출력 버퍼를 비우는 등 어쩌고저쩌고한 이유로 상당히 느립니다. (scanf, printf의 2배~8배 정도. 참고링크: https://algospot.com/forum/read/2496/)

게시글 목록