zoukankan      html  css  js  c++  java
  • PAT甲级专题|最短路

    PAT甲级最短路

    主要算法:dijkstra 求最短最长路、dfs图论搜索。

    1018,dijkstra记录路径 + dfs搜索路径最值

    25分,错误点暂时找不出。。
    如果只用dijkstra没法做,只能得20分

    #include<bits/stdc++.h>
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 510;
    int cmax,n,ter,m; 
    int caps[maxn];
    
    int g[maxn][maxn];
    int vis[maxn];
    vector<int> pre[maxn]; 
    int dist[maxn];
    int half;
    vector<int> paths;
    vector<int> temp;
    int minsend = inf;
    int mintake = inf;
    
    //dfs
    void dfs(int x){
    	temp.push_back(x);
    	if(x == 0){
    		int need = 0;
    		int take = 0;
    		for(int i=0;i<temp.size();i++){
    			if(temp[i] == 0) continue;
    			if(caps[temp[i]] - half > 0){ 
    				int d = caps[temp[i]] - half;
    				if(need >= d) need -= d;
    				else{
    					need = 0;
    					take += (d - need);
    				}
    			}else{ 
    				need += (half - caps[temp[i]]);
    			}
    		}
    		if(need < minsend){
    			minsend = need;
    			mintake = take;
    			paths = temp;
    		}else if(need == minsend){
    			if(mintake > take){
    				mintake = take;
    				paths = temp;
    			}
    		}
    		temp.pop_back();
    		return;	
    	}
    	for(int i=0;i<pre[x].size();i++){
    		dfs(pre[x][i]);
    	}
    	temp.pop_back();
    }
    
    void dijkstra(){
        memset(vis,0,sizeof(vis));
        memset(dist,inf,sizeof(dist));
        int half = cmax/2;
        dist[0] = 0;
        for(int i=0;i<=n;i++){
            int v,min_w = inf;
            for(int j=0;j<=n;j++){
                if(!vis[j] && dist[j] < min_w){
                    min_w = dist[j];
                    v = j;
                }
            }
            if(min_w == inf) return;
            vis[v] = 1;
            for(int j=0;j<=n;j++){
    			if(vis[j] || g[v][j] == inf) continue;
    			if(g[v][j] + dist[v] < dist[j]){
    				dist[j] = g[v][j] + dist[v];
    				pre[j].clear();
    				pre[j].push_back(v);
    			}else if(g[v][j] + dist[v] == dist[j]){
    				pre[j].push_back(v);
    			}
            }
        }
    }
    
    int main(){
    	memset(g,inf,sizeof(g));
        cin>>cmax>>n>>ter>>m;
        half = cmax/2;
        caps[0] = 0;
        for(int i=1;i<=n;i++) cin>>caps[i];
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            g[u][v] = w;
            g[v][u] = w;
        }
        dijkstra();
    	dfs(ter);
    	cout<<minsend<<" ";
    	for(int i=paths.size()-1;i>0;i--){
    		cout<<paths[i]<<"->";
    	}
    	cout<<paths[0];
    	cout<<" "<<mintake<<endl;
        return 0;
    }
    
    /*
    10 3 3 5
    6 7 10 
    0 1 1
    0 2 1
    0 3 2
    1 3 1
    2 3 1
    */ 
    

    1030,多边权,多条更新

    #include<bits/stdc++.h>
    using namespace std;
    
    /*
    dijkstra:双边权 
    */
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 510;
    int n,m,s,d;
    int dist[maxn];
    int path[maxn];
    int cost[maxn];
    int vis[maxn];
    struct edge{
    	int v,w,c;
    	edge(int vv,int ww,int cc){
    		v = vv;
    		w = ww;
    		c = cc;
    	}
    };
    vector<int> paths;
    vector<edge> g[maxn]; 
    
    void dijkstra(int ss){
        memset(vis,0,sizeof(vis));
        memset(dist,inf,sizeof(dist));
        memset(cost,inf,sizeof(cost));
        dist[ss] = 0;
        cost[ss] = 0;
        path[ss] = -1;
        for(int i=0;i<n;i++){
            int v,min_w = inf;
            for(int j=0;j<n;j++){
                if(!vis[j] && dist[j] < min_w){
                    min_w = dist[j];
                    v = j;
                }
            }
            if(min_w == inf) return;
            vis[v] = 1;
            for(int j=0;j<g[v].size();j++){
                int x = g[v][j].v;
                if(!vis[x] && dist[v] + g[v][j].w < dist[x]){
                	cost[x] = cost[v] + g[v][j].c;
                    dist[x] = dist[v] + g[v][j].w;
                    path[x] = v;
                }else if(!vis[x] && dist[v] + g[v][j].w == dist[x]){
    				if(cost[x] > cost[v] + g[v][j].c){
    					path[x] = v;
    					cost[x] = cost[v] + g[v][j].c;
    				}
                }
            }
        }
    }
    
    int main(){
    	cin>>n>>m>>s>>d;
    	for(int i=1;i<=m;i++){
    		int u,v,w,c;
    		cin>>u>>v>>w>>c;
    		g[u].push_back(edge(v,w,c));
    		g[v].push_back(edge(u,w,c));
    	}
    	dijkstra(s);
    	int cur = d;
    	while(cur != -1){
    		paths.push_back(cur);
    		cur = path[cur]; 
    	}
    	for(int i=paths.size()-1;i>=0;i--){
    		cout<<paths[i]<<" ";
    	}
    	cout<<dist[d]<<" "<<cost[d]<<endl;
    	return 0;
    } 
    

    1087,记录所有路径,dfs搜索路径最值

    #include<bits/stdc++.h>
    using namespace std;
    
    
    /*
    map映射:string <-> cityId  Name <-> Int 
    dijkstra:找出最短路的长度 以及所有最短路径(存入到pre容器中)
    dfs:统计最短路的数量 从终点触发在出口判断更新所需的权值 
    */
    const int inf = 0x3f3f3f3f;
    const int maxn = 210;
    map<string, int> mp;
    map<int,string> mp2;
    int n,k;
    string start;
    int haps[maxn];
    int g[maxn][maxn];
    int nums;
    int vis[maxn]; 
    int dist[maxn];
    int ter = 0;
    vector<int> pre[maxn];
    vector<int> temp,path;
    int maxhap = 0;
    double maxave = 0;
    
    void dfs(int x){
    	temp.push_back(x);
    	if(x == n){
    		int curhap = 0;
    		double curave = 0;
    		for(int i=temp.size()-1;i>=0;i--){
    			curhap += haps[temp[i]];
    		}
    		if(temp.size() == 1){
    			curave = 0;
    		}else{
    			curave = curhap*1.0/(temp.size()-1);
    		}
    		if(maxhap < curhap){
    			maxhap = curhap;
    			maxave = curave;
    			path = temp;
    		}else if(maxhap == curhap){
    			if(maxave < curave){
    				maxave = curave;
    				path = temp;
    			}
    		}
    		nums++;
    		temp.pop_back();
    		return;
    	}
    	for(int i=0;i<pre[x].size();i++){
    		dfs(pre[x][i]);
    	}
    	temp.pop_back();
    }
    
    void dijkstra(int s){
        memset(vis,0,sizeof(vis));
        memset(dist,inf,sizeof(dist));
        dist[s] = 0;
        for(int i=1;i<=n;i++){
            int v,min_w = inf;
            for(int j=1;j<=n;j++){
                if(!vis[j] && dist[j] < min_w){
                    v = j;
                    min_w = dist[j];
                }
            }
            vis[v] = 1;
            if(min_w == inf) return;
            for(int j=1;j<=n;j++){
                if(!vis[j] && g[v][j] != inf){
                    if(dist[j] > dist[v] + g[v][j]){
                    	dist[j] = dist[v] + g[v][j];
                    	pre[j].clear();
                    	pre[j].push_back(v);
                    }else if(dist[j] == dist[v] + g[v][j]){
                    	pre[j].push_back(v);
                    }
                }
            }
        }
    }
    
    int main(){
        memset(g,inf,sizeof(g));
        cin>>n>>k>>start;
        for(int i=1;i<=n-1;i++){
            string city;
            int hap;
            cin>>city>>hap;
            mp[city] = i;
            mp2[i] = city;
            haps[i] = hap;
        }
        mp[start] = n;
        mp2[n] = start;
        haps[n] = 0;
        for(int i=1;i<=k;i++){
            string c1,c2;
            int cost;
            cin>>c1>>c2>>cost;
            int u = mp[c1];
            int v = mp[c2];
            g[u][v] = cost;
            g[v][u] = cost;
        }
        ter = mp["ROM"];
        dijkstra(n);
        dfs(ter);
        cout<<nums<<" "<<dist[ter]<<" "<<maxhap<<" "<<int(maxave)<<endl;
        cout<<start;
        for(int i=path.size()-2;i>0;i--){
        	cout<<"->"<<mp2[path[i]];
    	}
    	cout<<"->ROM"<<endl;
        return 0;
    }
    

    1111,多边权、记录路径、多条件更新

    #include<bits/stdc++.h>
    using namespace std;
    
    /*
    30分 
    */
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 510;
    int source,ter;
    int n,m;
    int vis1[maxn];
    int vis2[maxn];
    struct edge{
        int v;
        int length;
        int time;
        edge(int vv,int len,int ti){
            v = vv;
            length = len;
            time = ti;
        }
    };
    vector<edge> g[maxn];
    int dist1[maxn];
    int time1[maxn];
    int time2[maxn];
    int path1[maxn];
    int path2[maxn];
    int nums[maxn];
    vector<int> ans1;
    vector<int> ans2;
    
    void dijkstra1(){
        memset(vis1,0,sizeof(vis1));
        memset(dist1,inf,sizeof(dist1));
        memset(time1,inf,sizeof(time1));
        dist1[source] = 0;
        time1[source] = 0;
        path1[source] = -1;
        for(int i=0;i<n;i++){
            int v,min_w = inf;
            for(int j=0;j<n;j++){
                if(!vis1[j] && dist1[j] < min_w){
                    v = j;
                    min_w = dist1[j];
                }
            }
            vis1[v] = 1;
            if(min_w == inf) return;
            for(int j=0;j<g[v].size();j++){
                int u = g[v][j].v;
                if(!vis1[u]){
                    if(dist1[u] > dist1[v] + g[v][j].length){
                        time1[u] = time1[v] + g[v][j].time;
                        dist1[u] = dist1[v] + g[v][j].length;
                        path1[u] = v;
                    }else if(dist1[u] == dist1[v] + g[v][j].length && time1[u] > time1[v] + g[v][j].time){
                        time1[u] = time1[v] + g[v][j].time;
                        path1[u] = v;
                    }
                }
            }
        }
    }
    
    
    void dijkstra2(){
        memset(vis2,0,sizeof(vis2));
        memset(nums,inf,sizeof(nums));
        memset(time2,inf,sizeof(time2));
        nums[source] = 1;
        time2[source] = 0;
        path2[source] = -1;
        for(int i=0;i<n;i++){
            int v,min_w = inf;
            for(int j=0;j<n;j++){
                if(!vis2[j] && time2[j] < min_w){
                    v = j;
                    min_w = time2[j];
                }
            }
            vis2[v] = 1;
            if(min_w == inf) return;
            for(int j=0;j<g[v].size();j++){
                int u = g[v][j].v;
                if(!vis2[u]){
                    if(time2[u] > time2[v] + g[v][j].time){
                        time2[u] = time2[v] + g[v][j].time;
                        nums[u] = nums[v] + 1;
                        path2[u] = v;
                    }else if(time2[u] == time2[v] + g[v][j].time){
                        if(nums[u] >= nums[v] + 1){
                            path2[u] = v;
                            nums[u] = nums[v] + 1;
                        }
                    }
                }
            }
        }
    }
    
    bool identical(){
        int cur = ter;
        while(cur != -1){
            ans1.push_back(cur);
            cur = path1[cur];
        }
        cur = ter;
        while(cur != -1){
            ans2.push_back(cur);
            cur = path2[cur];
        }
        reverse(ans1.begin(),ans1.end());
        reverse(ans2.begin(),ans2.end());
        if(ans1.size() != ans2.size()) return false;
        for(int i=0;i<ans1.size();i++){
            if(ans1[i] != ans2[i])return false;
        }
        return true;
    }
    
    int main(){
    //	freopen("in.txt", "r", stdin);
    //	freopen("out.txt", "w", stdout);
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            int v1,v2,one,length,time;
            cin>>v1>>v2>>one>>length>>time;
            if(one == 0){
                g[v1].push_back(edge(v2,length,time));
                g[v2].push_back(edge(v1,length,time));
            }else{
                g[v1].push_back(edge(v2,length,time));
            }
        }
        cin>>source>>ter;
        dijkstra1();
        dijkstra2();
        if(identical()){
            printf("Distance = %d; Time = %d: %d",dist1[ter],time2[ter],source);
            for(int i=1;i<ans1.size();i++){
                printf(" -> %d",ans1[i]);
            }
            printf("
    ");
        }else{
            printf("Distance = %d: %d",dist1[ter],source);
            for(int i=1;i<ans1.size();i++){
                printf(" -> %d",ans1[i]);
            }
            printf("
    ");
            printf("Time = %d: %d",time2[ter],source);
            for(int i=1;i<ans2.size();i++){
                printf(" -> %d",ans2[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    /*
    4 4
    0 1 1 1 2
    0 2 1 2 1
    1 3 1 2 2
    2 3 1 1 1
    0 3
    */
    
  • 相关阅读:
    如何在Mac终端中进入含空格文件名的文件夹
    redis测试常用工具及方法
    Spark3.0 Standalone模式部署
    使用Quorum Journal Manager(QJM)的HDFS NameNode高可用配置
    任务-实业-化工:王永庆
    节日-传统节日:排灯节
    葡萄科:乌蔹梅
    植物界:蕨类植物门
    修辞手法-汉语-词语:明喻
    修辞手法-汉语-词语:隐喻
  • 原文地址:https://www.cnblogs.com/fisherss/p/11577726.html
Copyright © 2011-2022 走看看