ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ACM集训队个人赛5 I 题题解

2021-09-21 10:36:39  阅读:192  来源: 互联网

标签:10 crq 集训队 int 题解 城市 ACM add include


原题链接:xinz

描述

crq没钱出去玩,只好自己虚拟旅行,它找了很多很多的地名(都是A~J开头,太多找不动了),想要从任意一个A开头的地名,再去一个B开头的地名,以此类推,直到J开头的地名结束旅行(中间没有重复且不漏,即不会有两个地名的第一个字母相同,也不会缺掉某个字母开头)。

crq查了几条路线,给每条路标记了花费,他想知道花费最少的一条路线。

输入

第一行为数据组数t,接下来有t组数据。

每组数据的第一行为n(10<=n<=105)和m(9<=m<=106),表示地名数量和道路条数。

接下来n行,每行一个字符串表示地名(都是大写字母A~J开头,后面都是小写字母,长度不超过10)。

接下来有m行,每行为两个字符串u和v,一个整数w,其中u和v为地名(在给定列表中),w为u到v的花费(1<=w<=1000),路线是双向的且来回的花费相同。

数据保证一定存在一条路线。

注意:crq可以经过某个城市不玩,比如A到C有路,且C到B有路,crq也可以A到B。

输出

每组在一行中输出花费最少的一条路线所需的花费值。

样例输入

1
11 10
Anhui
Anqing
Beijing
Chongqing
Denghuang
Europe
Fuzhou
Guangzhou
Hangzhou
Italy
Jiaojiang
Anhui Jiaojiang 1
Jiaojiang Anqing 2
Italy Jiaojiang 1
Guangzhou Italy 1
Hangzhou Guangzhou 1
Fuzhou Hangzhou 1
Europe Fuzhou 1
Europe Denghuang 1
Denghuang Chongqing 1
Beijing Chongqing 1

样例输出

19

题解

  • 如题所示crq必须先到 A 旅行,在到 B 旅行,再到 C 旅行.....最后再J城结束旅行。又因为可以经过这个城市不玩,所以我们可以通过经过其他城市来到达想要去的城市。
  • 很明显这个图是一个分层图,我们可以将最后已经到达的城市进行分层( 比如说 crq现在在首字母为 C 的城市,但是,他没有经过 B 城市,所以这一层应该是为第一层,然后他将要去首字母为 B 城市,那么这一层就转换成了第二层)之后我们建立一个超级源点和一个超级汇点,对每个 A 城市与 0 号点建边,每个 J 城市与 n+1 号点建边,最后只要输出 n+1 号点的第 10 层(依次递推 J 应为 10 )即为答案
  • 分层图不熟悉的可以看 拯救大兵瑞典 链接 :xinz

最终AC代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
const int N=1e5+5,M=4e6+5;//因为要与超级源点与超级汇点建边,所以 M 的值要大一点
typedef long long ll;
map<string,int>mp;//城市的编号
int op[N];//城市的首字母
int h[N],ne[M],w[M],e[M],idx;
int n,m;
ll f[N][12];
bool st[N][12];
void add(int a,int b,int c){
    e[idx]=b;w[idx]=c;
    ne[idx]=h[a];h[a]=idx++;
}
struct aa{
    int x,y;
};
ll spfa(){
    memset(f,0x3f,sizeof(f));
    queue<aa>que;
    que.push({0,0});
    st[0][0]=1;f[0][0]=0;
    while(que.size()){
        aa b=que.front();que.pop();
        st[b.x][b.y]=0;
        int u=b.x;
        for(int i=h[u];~i;i=ne[i]){
            int j=e[i],t=b.y;
            if(t+1==op[j])t++;//假如说要去的城市与下一层相同,则层数加一
            if(f[j][t]>f[u][b.y]+w[i]){
                f[j][t]=f[u][b.y]+w[i];
                if(!st[j][t])que.push({j,t}),st[j][t]=1;
            }
        }
    }
    return f[n+1][10];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--){
        memset(h,-1,sizeof(h));
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            string s;
            cin>>s;
            mp[s]=i;
            op[i]=s[0]-'A'+1;//第 i 个城市的首字母是什么
            if(s[0]=='A')add(0,i,0);
            else if(s[0]=='J')add(i,n+1,0);
        }
        while(m--){
            string s1,s2;
            int c;
            cin>>s1>>s2>>c;
            int a=mp[s1],b=mp[s2];
            add(a,b,c);add(b,a,c);
        }
        cout<<spfa()<<endl;
    }
    return 0;
}

标签:10,crq,集训队,int,题解,城市,ACM,add,include
来源: https://www.cnblogs.com/syf2020/p/15316070.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有