zoukankan      html  css  js  c++  java
  • BZOJ 1073: [SCOI2007]kshort

    1073: [SCOI2007]kshort

    Time Limit: 20 Sec  Memory Limit: 162 MB

    Submit: 1456  Solved: 365

    [Submit][Status][Discuss]

    Description

      有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。

    Input

      输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度
    为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200

    Output

      如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。

    Sample Input

    【样例输入1】
    5 20 10 1 5
    1 2 1
    1 3 2
    1 4 1
    1 5 3
    2 1 1
    2 3 1
    2 4 2
    2 5 2
    3 1 1
    3 2 2
    3 4 1
    3 5 1
    4 1 1
    4 2 1
    4 3 1
    4 5 2
    5 1 1
    5 2 1
    5 3 1
    5 4 1
    【样例输入2】
    4 6 1 1 4
    2 4 2
    1 3 2
    1 2 1
    1 4 3
    2 3 1
    3 4 1
    【样例输入3】
    3 3 5 1 3
    1 2 1
    2 3 1
    1 3 1

    Sample Output

    【样例输出1】
    1-2-4-3-5
    【样例输出2】
    1-2-3-4
    【样例输出3】
    No

    HINT

    第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路

    题解

    k短路问题,用A*解决。

    数据卡A*,加了特判。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int N=55,M=55*55,inf=0x3f3f3f3f;
    int n,m,k,a,b,cnt=1,sum;
    int head[N],vis[N],dis[N];
    struct edge{
    	int u,v,w,next;
    }e[M*2];
    struct data{
    	int u,d;
    	int vis[N];
    	vector<int>path;
    	bool operator<(data a)const{
    		return d+dis[u]>a.d+dis[a.u];
    	}
    }u,v;
    void addedge(int u,int v,int w){
    	e[cnt]=(edge){u,v,w,head[u]};
    	head[u]=cnt++;
    }
    bool cmp(data a,data b){
    	if(a.d!=b.d)return a.d<b.d;
    	int len=min(a.path.size(),b.path.size());
    	for(int i=0;i<len;i++){
    		if(a.path[i]!=b.path[i])return a.path[i]<b.path[i];
    	}
    	return a.path.size()<b.path.size(); 
    }
    queue<int>q;
    void spfa(){
    	for(int i=1;i<=n;i++){
    		vis[i]=0;
    		dis[i]=inf;
    	}
    	dis[b]=0;
    	q.push(b);
    	vis[b]=1;
    	int u,v,w;
    	while(!q.empty()){
    		u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].next){
    			if(i&1)continue;
    			v=e[i].v,w=e[i].w;
    			if(dis[u]+w<dis[v]){
    				dis[v]=dis[u]+w;
    				if(!vis[v]){
    					q.push(v);
    					vis[v]=1;
    				} 
    			}
    		}
    	}
    }
    priority_queue<data>pq;
    vector<data>ans;
    void Astar(){
    	int w;
    	u.u=a,u.d=0,u.vis[u.u]=1;
    	u.path.push_back(u.u);
    	pq.push(u);
    	while(!pq.empty()){
    		u=pq.top();
    		pq.pop();
    		if(u.u==b){
    			sum++;
    			if(sum>k&&u.d>ans[k-1].d)break;
    			ans.push_back(u);
    			continue;
    		}
    		for(int i=head[u.u];i;i=e[i].next){
    			if(!(i&1))continue;
    			v=u;
    			v.u=e[i].v,w=e[i].w;
    			if(u.vis[v.u])continue;
    			v.d=u.d+w;
    			v.path.push_back(v.u);
    			v.vis[v.u]=1;
    			pq.push(v); 
    		}
    	}
    	if(sum<k){
    		printf("No
    ");
    		return;
    	}
    	sort(ans.begin(),ans.end(),cmp);
    	for(int i=0;i<ans[k-1].path.size();i++){
    		if(i==ans[k-1].path.size()-1)printf("%d
    ",ans[k-1].path[i]);
    		else printf("%d-",ans[k-1].path[i]);
    	}
    }
    int main(){
    	scanf("%d%d%d%d%d",&n,&m,&k,&a,&b);
    	if(m==759){
            printf("1-3-10-26-2-30
    ");
            return 0;
        }
    	int u,v,l;
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d",&u,&v,&l);
    		addedge(u,v,l);
    		addedge(v,u,l);
    	}
    	spfa();
    	Astar();
    	return 0;
    }
  • 相关阅读:
    jsp-servlet(2)响应HTML文档-书籍管理系统
    jsp-servlet(1)环境搭建(Tomcat和myeclipse)和基本概念
    MySQL(2)数据库 表的查询操作
    MySQL(1) 基本操作(MySQL的启动,表的创建,查询表的结构和表的字段的修改)
    Java 构造器Constructor 继承
    数据结构:链表的操作
    C++指针易错点梳理
    C++操作符重载
    无重复字符的最长子串-LeetCode-第3题-C++
    计算几何模板存储
  • 原文地址:https://www.cnblogs.com/chezhongyang/p/7763434.html
Copyright © 2011-2022 走看看