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;

/*
18分
*/

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("\n");
    }else{
        printf("Distance = %d: %d",dist1[ter],source);
        for(int i=1;i<ans1.size();i++){
            printf(" -> %d",ans1[i]);
        }
        printf("\n");
        printf("Time = %d: %d",time2[ter],source);
        for(int i=1;i<ans2.size();i++){
            printf(" -> %d",ans2[i]);
        }
        printf("\n");
    }
    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
*/

原文地址:https://www.cnblogs.com/fisherss/p/11577726.html

时间: 2024-10-06 15:26:11

PAT甲级专题|最短路的相关文章

PAT甲级1005 Spell It Right

题目:PAT甲级 1005 题解:水题.看到题目的第一时间就在想一位一位的mod,最后一加一转换就完事了.结果看到了N最大为10的100的次方,吓得我赶紧放弃这个想法... 发现碰到这种情况用字符串十分好用,这道题应该考察的就是这一点.大致思路就是把数字的每一位放到字符串中,然后通过ASCII码得到每一位的相加结果num,然后把num一位一位的放到stack中,使用stack是因为它先进先出的特性,最后输出就行了. 代码: 1 #include<cstdio> 2 #include<qu

PAT甲级考前整理

终于在考前,刷完PAT甲级130道题目,不容易!!!每天沉迷在刷题之中而不能超脱,也是一种境界.PAT甲级题目总的说卡题目的比较多,卡测试点的比较少,有些题目还会有题意混淆,这点就不吐槽了吧.静下心来耍这130道题,其实磨练的是一种态度与手感,养成的是一种习惯.热爱AC没有错!! 130道题目主要的考点: 1.排序:快速排序,直接插入排序,希尔排序,分治排序,堆排序. 2.图论:拓扑排序.最短路径.深度搜索.广度搜索. 3.树:树的遍历.完全二叉树.AVL. 4.其他:并查集,模拟,哈希.背包.

PAT甲级考试题库1001 A+B Format 代码实现及相关知识学习

准备参加九年九月份的PAT甲级证书考试,对网站上的题目进行总结分析: 1001题 A+B Format (20 分) Calculate a+b and output the sum in standard format -- that is, the digits must be separated into groups of three by commas (unless there are less than four digits). 计算a+b的值并以一定格式输出其和sum(数字需要

【PAT甲级】1070 Mooncake (25 分)(贪心水中水)

题意: 输入两个正整数N和M(存疑M是否为整数,N<=1000,M<=500)表示月饼的种数和市场对于月饼的最大需求,接着输入N个正整数表示某种月饼的库存,再输入N个正数表示某种月饼库存全部出手的利润.输出最大利润. trick: 测试点2可能包含M不为整数的数据.(尽管题面说明M是正整数,可是根据从前PAT甲级题目的经验,有可能不是整数.....) 代码: #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using names

【PAT L2-001】最短路计数

给定一个无向带权网络,无负边,无重边和自环,每个顶点有一个正数权值.首先求特定原点s到终点d的最短路的个数:然后求所有最短路中顶点权值a[i]之和最大的那条,输出这条路径. 可用dijkstra算法求出所有最短路,用一个pathNum[u]数组记录从s到u的最短路的个数,查找链path[u]保存了到u为止使顶点权值a[i]之和最大的那条路径,sum[u]保存了这条路径的顶点权值和. 对于提交后的第3个测试点,注意更新新引入顶点u的邻居v的距离值dis[v]时,sum[v]无条件更新为sum[u]

PAT 甲级 1003. Emergency (25)

1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount

PAT甲级第二次真题练习

1005 Spell It Right (20)(20 分)提问 Given a non-negative integer N, your task is to compute the sum of all the digits of N, and output every digit of the sum in English. Input Specification: Each input file contains one test case. Each case occupies one

PAT 甲级 1035 Password

https://pintia.cn/problem-sets/994805342720868352/problems/994805454989803520 To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem is that there are always some confusing passwords since it is hard to di

pat甲级 1001 A+B Format

要写甲级题,首要任务是解决英文这个大难题. 困难词汇(我不认识的):calculate计算  standard format 标准格式  digits数字  separated 分离  commas逗号 这道题的大致意思是,给出两个数a和b,并且a和b都大于等于-10的6次方小于等于10的6次方,求出a和b的和,将这个和,每三个数字用逗号分隔一下.看懂了题意以后这题就简单了 ac代码如下: #include <iostream> #include<string> #include&