• bzoj1598: [Usaco2008 Mar]牛跑步


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1598

    思路:裸的k短路,直接用A*+堆即可

    A*就是引入一个估价函数h(x)=f(x)+g(x)

    优先选择估价小的去搜索

    f(x)就是当前到的x已花费代价

    g(x)就是估计x到终点还要多少代价

    这里f(x)就是出发点S到x的距离

    g(x)就是x到终止点T的距离

    g(x)可以再反图上跑一遍dijksta+heap预处理出来


    过程就是一个类bfs过程

    首先把S扔进优先队列

    从优先队列中取出f(x)最小的点x

    如果x==T,那么就又找到了一条路径,如果已经到T K次了,那么就找到了K短路

    否则就把相邻的点扩展进来,加入优先队列中。

    如果s==t,k要加1

    时间复杂度:O(玄学) O(nk)

    一个n元环就把它卡废了....


    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define PI pair<int,int>
    #define fi first
    #define se second
    #define mp(a,b) make_pair(a,b)
    const int maxn=100010,maxm=100010;
    using namespace std;
    int n,m,K,cnt[maxn],pre[maxm],now[maxn],son[maxm],val[maxm],tot,dis[maxn],S,T,inf,ans[maxn];
    void add(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    priority_queue<PI,vector<PI>,greater<PI> > q;
    
    struct Topp_graph{
    	int pre[maxm],now[maxn],son[maxm],val[maxm],tot;
    	void add(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    	void dijkstra(){
    		memset(dis,63,sizeof(dis)),inf=dis[0];
    		dis[T]=0,q.push(mp(0,T));
    		while (!q.empty()){
    			int x=q.top().se,d=q.top().fi;
    			q.pop();
    			for (int y=now[x];y;y=pre[y])
    				if (dis[son[y]]>d+val[y]){
    					dis[son[y]]=d+val[y];
    					q.push(mp(dis[son[y]],son[y]));
    				}
    		}
    		while (!q.empty()) q.pop();
    	}
    	
    }opp;
    
    void Astar(){
    	memset(ans,-1,sizeof(ans));
    	if (dis[S]==inf) return;
    	q.push(mp(dis[S],S));
    	while (!q.empty()){
    		int x=q.top().se,d=q.top().fi;
    		cnt[x]++,q.pop();
    		if (x==T) ans[cnt[x]]=d;
    		for (int y=now[x];y;y=pre[y])
    			if (cnt[x]<=K)
    				q.push(mp(dis[son[y]]+d-dis[x]+val[y],son[y]));
    	}
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&K),S=n,T=1;
    	for (int i=1,x,y,z;i<=m;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),opp.add(y,x,z);
    	opp.dijkstra(),Astar();
    	for (int i=1;i<=K;i++) printf("%d
    ",ans[i]);
    	//for (int i=1;i<=n;i++) printf("%d
    ",dis[i]);
    	return 0;
    }


  • 相关阅读:
    [转] 献给所有正在找路的人
    在同一表单内,多个提交按钮的处理方式
    javascript高级选择器querySelector和querySelectorAll
    一位年轻女董事长的37条忠告很受启发吧?
    函数的延迟加载
    WCF的CommunicationObjectFaultedException异常问题
    WCF Test Client对象数组输入问题
    [转载]C#开发Winform记录用户登录状态的方法
    using(C#)
    使用 SCTP 优化网络
  • 原文地址:https://www.cnblogs.com/thythy/p/5493633.html
Copyright © 2020-2023  润新知