차 단락 (두 가지 방식) & & K 단락

7091 단어 데이터 구조
차 단락 알고리즘:
두 가지 비교적 간단하게 단락 을 실현 하 는 사상 이 있다.
  • 방법 1: dijkstra 알고리즘 으로 시작 하여 [최 단 로 배열 (dis1 [])] 과 [차 단락 배열 (dis2 []]]]
  • 을 동시에 유지 합 니 다.
  • 방법 2: dijkstra 알고리즘 을 사용 하여 각각 두 개의 dis1 [] 배열 과  dis2 [] 배열 은 각각 출발점 과 종점 에서 시작 하 는 최 단 로 를 유지 합 니 다. 그리고 모든 변 을 매 거 합 니 다. 변 의 두 점 을 출발점 과 종점 에 연결 하여 최 단 로 와 같 는 지, 같 지 않 으 면 건 너 뛰 고 같 지 않 으 면 업데이트 와 차 단락 (Inf) 은 min
  • 을 가 져 옵 니 다.
    제목: POJ - 3255
    방식 1:
    tips: 그 중 if (dis2 [v] < w) continue;이 말 이 true 일 때 현재 노드 v 의 차 단락 이 이미 업데이트 되 었 음 을 설명 합 니 다. 만약 에 w 가 차 단락 보다 크다 면 이것 은 틀림없이 > = 세 번 째 단락 이 고 업데이트 할 필요 가 없습니다.
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    typedef long long LL;
    const int Maxn = 1e5 + 7;
    const int Inf = 1e9 + 7;
    int N , M;
    int dis1[Maxn] , dis2[Maxn];
    struct node{
    	int v , w;
    	friend bool operator < (node a , node b){
    		return a.w > b.w;
    	}
    };
    vector  G[Maxn];
    void Dijkstra(){
    	priority_queue  que;
    	fill(dis1 , dis1+N+1 , Inf);
    	fill(dis2 , dis2+N+1 , Inf);
    	int start = 1;
    	dis1[start] = 0;
    	que.push((node){start , 0});
    	node q;
    	int v , w;
    	while(!que.empty()){
    		q = que.top();	que.pop();
    		v = q.v , w = q.w;
    		if(dis2[v] < w)	continue;
    		int to_v , to_w;
    		for(int i = 0 ; i < G[v].size() ; i++){
    			to_v = G[v][i].v , to_w = G[v][i].w + w;
    			if(dis1[to_v] > to_w){
    				que.push((node){to_v , to_w});
    				swap(dis1[to_v] , to_w);
    			}
    			if(dis2[to_v] > to_w && dis1[to_w] < to_w){
    				dis2[to_v] = to_w;
    				que.push((node){to_v , to_w});
    			}
    		}
    	}
    
    }
    
    int main()
    {
    	while(~scanf(" %d %d",&N,&M)){
    		for(int i = 1 ; i <= M ; i++){
    			int u , v , w;	scanf(" %d %d %d",&u,&v,&w);
    			G[u].push_back((node){v,w});
    			G[v].push_back((node){u,w});
    		}
    		Dijkstra();
    		printf("%d
    ",dis2[N]); } }

    방식 2:
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    typedef long long LL;
    const int Maxn = 1e5 + 7;
    const int Inf = 1e9 + 7;
    int N , M , cnt , ans;
    int start = 1 , End = N;
    int dis1[Maxn] , dis2[Maxn];
    bool vis[Maxn];
    struct node{
    	int v , w;
    	friend bool operator < (node a , node b){
    		return a.w > b.w;
    	}
    };
    struct edge{
    	int x , y , w;
    }A[Maxn << 1];
    vector  G[Maxn];
    
    void GetDis(int op){
    	priority_queue  que;
    	if(!op)	que.push((node){start , 0});
    	else	que.push((node){End , 0});
    	int v , w;
    	node q;
    	while(!que.empty()){
    		q = que.top();	que.pop();
    		v = q.v , w = q.w;
    		if(vis[v])	continue;
    		vis[v] = true;
    		int to_v , to_w;
    		for(int i = 0 ; i < G[v].size() ; i++){
    			to_v = G[v][i].v , to_w = G[v][i].w + w;
    			if(!op && dis1[to_v] > to_w){
    				dis1[to_v] = to_w;
    				que.push((node){to_v , to_w});
    			} else if(op && dis2[to_v] > to_w){
    				dis2[to_v] = to_w;
    				que.push((node){to_v , to_w});
    			}
    		}
    	}
    }
    
    
    void Dijkstra(){
    	fill(dis1 , dis1+N+1 , Inf);
    	fill(dis2 , dis2+N+1 , Inf);
    	start = 1 , End = N;
    	dis1[start] = dis2[End] = 0;
    	fill(vis , vis+N+1 , false);
    	GetDis(0);
    	fill(vis , vis+N+1 , false);
    	GetDis(1);
    }
    void FindCdl(){
    	int flag = dis1[End];
    	int x , y , w;
    	ans = Inf;
    	for(int i = 1 ; i <= cnt ; i++){
    		x = A[i].x , y = A[i].y , w = A[i].w;
    		int temp = dis1[x] + dis2[y] + w;
    		if(temp == flag)	continue;
    		else ans = min(ans , temp);
    	}
    }
    
    int main()
    {
    	while(~scanf(" %d %d",&N,&M)){
    		cnt = 0;
    		for(int i = 1 ; i <= M ; i++){
    			int u , v , w;	scanf(" %d %d %d",&u,&v,&w);
    			G[u].push_back((node){v,w});
    			G[v].push_back((node){u,w});
    			A[++cnt].x = u , A[cnt].y = v , A[cnt].w = w;
    			A[++cnt].x = v , A[cnt].y = u , A[cnt].w = w;
    		}
    		Dijkstra();
    		FindCdl();
    		printf("%d
    ",ans); } }

     
    제 K 단락:
    제 K 단락 사실은 BFS + A * (A * = = = 계발 식 검색 = = 가지치기 최적화)
    우선 종점 에서 각 점 까지 의 최 단 로 를 dis [] 배열 로 저장 하 십시오.
    그리고 A * 함수, F [x] = H [x] + G [x] 를 사용 합 니 다.
    제목: POJ 2449
    구체 적 인 설명 은 코드 안에 있다.
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    typedef long long LL;
    const int Maxn = 1e5 + 7;
    const int Inf = 1e9 + 7;
    int N , M , K;
    int start , End;
    int ans;
    
    //     
    int dis[Maxn];
    bool vis[Maxn];
    struct node{
    	int v , w;
    	friend bool operator < (node a , node b){
    		return a.w > b.w;
    	}
    };
    
    /*
     * A*         F[x] = H[x] + G[x]
     *    Hx               
     *    Gx       (            ,    )
     */
    struct edge{
    	int v , Hx , Gx;
    	friend bool operator < (edge a , edge b){
    		return a.Hx + a.Gx > b.Hx + b.Gx;
    	}
    };
    /*
     * count      BFS     
     *   count == K               (            K  )
     */
    int Count[Maxn];
    
    vector  G[Maxn] , G2[Maxn];
    
    /*
     * (            )
     *  End        
     */
    void Dijkstra(){
    	fill(vis , vis+N+1 , false);
    	fill(dis , dis+N+1 , Inf);
    	priority_queue  que;
    	que.push((node){End , 0});
    	dis[End] = 0;
    	node q;
    	int v , w;
    	while(!que.empty()){
    		q = que.top(); que.pop();
    		v = q.v , w = q.w;
    		if(vis[v])	continue;
    		vis[v] = true;
    		int to_v , to_w;
    		for(int i = 0 ; i < G2[v].size() ; i++){
    			to_v = G2[v][i].v , to_w = G2[v][i].w + w;
    			if(dis[to_v] > to_w){
    				dis[to_v] = to_w;
    				que.push((node){to_v , to_w});
    			}
    		}
    	}
    }
    /*
     *  K     = A* + BFS
     */
    void Astar(){
    	ans = -1;
    	fill(Count , Count+N+1 , 0);
    	priority_queue  que;
    	que.push((edge){start , 0 , 0});
    	edge q;
    	int v , Hx , Gx;
    	while(!que.empty()){
    		q = que.top(); que.pop();
    		v = q.v , Hx = q.Hx , Gx = q.Gx;
    		Count[v]++;
    		if(Count[v] == K && v == End){
    			ans = Hx + Gx;
    			break;
    		}
    		if(Count[v] > K)	continue;
    		int to_v , to_hx , to_gx;
    		for(int i = 0 ; i < G[v].size() ; i++){
    			to_v = G[v][i].v;
    			to_hx = Hx + G[v][i].w;
    			to_gx = dis[to_v];
    			que.push((edge){to_v , to_hx , to_gx});
    		}
    	}
    	while(!que.empty())	que.pop();
    	return;
    }
    
    int main()
    {
    	while(~scanf(" %d %d",&N,&M)){
    		for(int i = 1 ; i <= N ; i++)	G[i].clear();
    		for(int i = 1 ; i <= M ; i++){
    			int u , v , w;	scanf(" %d %d %d",&u,&v,&w);
    			G[u].push_back((node){v, w});
    			G2[v].push_back((node){u, w});
    		}
    		scanf(" %d %d %d",&start , &End , &K);
    		//    start End            0 ,  K++
    		if(start == End)	K++;
    		Dijkstra();
    		Astar();
    		printf("%d
    ",ans); } return 0; }

    좋은 웹페이지 즐겨찾기