HDU 3631 Shortest Path(Floyd + 플러그인)

2361 단어 도론
제목: n개의 점 m줄 테두리(단방향 테두리)와 q차 조작을 드리겠습니다. 처음에는 모든 점이 표시가 없습니다. 두 가지 조작이 있습니다. 1.0 x: x를 표시하고 가까이 표시한 경우 "ERROR! At point x"를 출력합니다. 2.1 u v: u에서 v까지의 최단길을 묻고 모두 표시된 점을 요구합니다. 그렇지 않으면 "ERROR! At path x to y"를 출력하고, 도착하지 않으면 "No such path"를 출력하고, 있으면 최단 경로 크기를 출력합니다.
 
분석: 본 문제의 제한은 바로 두 점 사이의 최단길은 표시된 점을 거쳐야 한다. 한 점을 표시하면 최단길을 갱신할 생각을 하기 쉽다. 왜냐하면 n<=300이고 매번 물어볼 때마다 임의의 두 점 사이의 최단길을 구하기 때문에 자연스럽게floyd(매번 최단로를 갱신할 때 새로 표시된 점을 중계점으로 Floyd를 뛴다)를 생각하기 때문이다.
#include
#include
#include
using namespace std;
const int N = 3e2 + 5;
const long long Inf = 1e12;
long long dis[N][N];
void floyd(int k, int n) {
    for(int i = 0; i < n; i += 1) {
        for(int j = 0; j < n; j += 1) {
            dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
        }
    }
}
bool vis[N];
void init(int n) {
    for(int i = 0; i < n; i += 1) {
        dis[i][i] = 0;
        vis[i] = false;
        for(int j = i + 1; j < n; j += 1) {
            dis[i][j] = dis[j][i] = Inf;
        }
    }
}
int main() {
    int v, e, Q, cas = 1;
    while(~scanf("%d%d%d", &v, &e, &Q)) {
        if(v + e + Q == 0)
            break;
        init(v);
        int x, y;
        long long wi;
        for(int i = 0; i < e; i += 1) {
            scanf("%d%d%lld", &x, &y, &wi);
            dis[x][y] = min(dis[x][y], wi);
        }
        int op;
        if(cas>1) printf("
"); printf("Case %d:
", cas); cas += 1; while(Q--) { scanf("%d", &op); if(op == 0) { scanf("%d", &x); if(vis[x]) printf("ERROR! At point %d
", x); else { vis[x] = true; floyd(x, v); } } else { scanf("%d%d", &x, &y); if(!vis[x] || !vis[y]) printf("ERROR! At path %d to %d
", x, y); else if(dis[x][y] == Inf) printf("No such path
"); else printf("%lld
", dis[x][y]); } } } return 0; }

 

좋은 웹페이지 즐겨찾기