zoukankan      html  css  js  c++  java
  • hdu 2923Einbahnstrasse(spfa/floyd+map)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2923

    题目意思:有n个城市,城市是用字符串表示的,c个城市有坏的车,r条有向有权道路,求从你在所在的城市,将坏的车拖回来的花费。

    思路:思路蛮简单,就是用map将城市(字符串)转化成编号,再求最短路,就是map处理稍微复杂点。

    开始我没仔细看数据大小,用spfa做的,代码量较多,但都是重复的代码,要正向建图求到坏车的花费,在反向建图求回来的花费。而用floyd就不用了,正常求就行。

    但是这题坑点是真的多,都快被坑哭了。我先列列坑点:

    1.一个城市可能有很多辆坏的车, 所以需要用一个数组存储坏车所在城市。

    2.一次只能拖一辆车。。。。一点也不符合实际,拖车店要亏死。

    3.两个城市间会有n条路,用前向星储存的还好,有数组存的可能就错了,还要比较,存最短的路。

    还有记得每次清除map。

    spfa:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<map>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+10;
    map<string,int>m;
    struct node{
        int u,v,w,next;
    }edge1[maxn],edge2[maxn];
    int head1[maxn],head2[maxn],visit[maxn];
    int d1[maxn],d2[maxn],cnt1,cnt2;
    int n,c,r,ans,aim[maxn];
    
    void init(){//初始化 
        m.clear();
        memset(head1,-1,sizeof(head1));
        memset(head2,-1,sizeof(head2));
        memset(d1,0x3f,sizeof(d1));
        memset(d2,0x3f,sizeof(d2));
        memset(aim,0,sizeof(aim));
        cnt1=cnt2=ans=0;
    }
    
    void add1(int u,int v,int w){//正向建图连边 
        edge1[cnt1].v=v;
        edge1[cnt1].w=w;
        edge1[cnt1].next=head1[u];
        head1[u]=cnt1++;
    }
    
    void add2(int u,int v,int w){//反向建图连边 
        edge2[cnt2].v=v;
        edge2[cnt2].w=w;
        edge2[cnt2].next=head2[u];
        head2[u]=cnt2++;
    }
    
    void spfa1(){// 求到坏车的花费 
        queue<int>q;
        memset(visit,0,sizeof(visit));
        q.push(aim[1]);
        d1[aim[1]]=0;
        visit[aim[1]]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            visit[u]=0;
            for(int i=head1[u];i!=-1;i=edge1[i].next){
                int v=edge1[i].v;
                int w=edge1[i].w;
                if(d1[v]>d1[u]+w){
                    d1[v]=d1[u]+w;
                    if(!visit[v]){
                        visit[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    
    void spfa2(){//求回来的花费 
        queue<int>q;
        memset(visit,0,sizeof(visit));
        q.push(aim[1]);
        d2[aim[1]]=0;
        visit[aim[1]]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            visit[u]=0;
            for(int i=head2[u];i!=-1;i=edge2[i].next){
                int v=edge2[i].v;
                int w=edge2[i].w;
                if(d2[v]>d2[u]+w){
                    d2[v]=d2[u]+w;
                    if(!visit[v]){
                        visit[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main(){
        std::ios::sync_with_stdio(false);
        int k=1;
        while(cin>>n>>c>>r&&(n||c||r)){
            init();
            string s,s1,s2;
            int num=1;
            for(int i=1;i<=c+1;i++){
                cin>>s;
                if(!m[s])
                    m[s]=num++;
                aim[i]=m[s];//用 aim存每个坏车所在城市的编号 
            }
            for(int i=0;i<r;i++){//map处理路的关系。 
                cin>>s>>s1>>s2;
                if(!m[s])//记得这里要写 
                    m[s]=num++;
                if(!m[s2])
                    m[s2]=num++;
                int len=s1.size(),w=0;
                for(int j=0;j<len;j++){
                    if(s1[j]>='0'&&s1[j]<='9')
                        w=w*10+s1[j]-'0';    
                }
                if(s1[0]=='<'){
                    add1(m[s2],m[s],w);//正向建图 
                    add2(m[s],m[s2],w);//方向建图 
                }
                if(s1[len-1]=='>'){
                    add1(m[s],m[s2],w);
                    add2(m[s2],m[s],w);
                }    
            }
            spfa1();
            spfa2();
            for(int i=2;i<=c+1;i++)
                ans+=d1[aim[i]]+d2[aim[i]];
            cout<<k++<<". "<<ans<<endl;
        }
        return 0;
    }
    View Code

    floyd:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<map>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+100;
    map<string,int>m;
    int mp[maxn][maxn],aim[maxn];
    int n,c,r,ans;
    
    void init(){//初始化 
        m.clear();//记得每次清除map 
        memset(mp,0x3f,sizeof(mp));
        memset(aim,0,sizeof(aim));
    }
    
    void floyd(){//floyd求最短路 
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    if(mp[i][j]>mp[i][k]+mp[k][j])
                        mp[i][j]=mp[i][k]+mp[k][j];
                }
    }
    
    int main(){
        std::ios::sync_with_stdio(false);
        int k=1;
        while(cin>>n>>c>>r&&(n||c||r)){
            init();
            ans=0;
            string s,s1,s2;
            int num=0;
            for(int i=1;i<=c+1;i++){
                cin>>s;
                if(!m[s]){
                    m[s]=++num;
                }
                aim[i]=m[s];//aim储存城市编号 
            }
            for(int i=0;i<r;i++){
                cin>>s>>s1>>s2;
                if(!m[s])
                    m[s]=++num;
                if(!m[s2])
                    m[s2]=++num;
                int len=s1.size(),w=0;
                for(int j=0;j<len;j++){
                    if(s1[j]>='0'&&s1[j]<='9')
                        w=w*10+s1[j]-'0';    
                }
                if(s1[0]=='<'){
                    mp[m[s2]][m[s]]=min(mp[m[s2]][m[s]],w);//记得取最小的边 
                }
                if(s1[len-1]=='>'){
                    mp[m[s]][m[s2]]=min(mp[m[s]][m[s2]],w);
                }    
            }
            floyd();
            for(int i=2;i<=c+1;i++)
                ans+=mp[aim[1]][aim[i]]+mp[aim[i]][aim[1]];
            cout<<k++<<". "<<ans<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Typescript类、命名空间、模块
    TypeScript 基础类型、变量声明、函数、联合类型、接口
    JS中的单线程与多线程、事件循环与消息队列、宏任务与微任务
    wangEditor上传本地视频
    java版excel转pdf,word转pdf
    idea2019.3 没有 Autoscroll from Source
    mysql 实现类似oracle函数bitand功能
    spring boot 配置文件动态更新原理 以Nacos为例
    spring boot 发布自动生成svn版本号
    spring boot JPA 数据库连接池释放
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10301187.html
Copyright © 2011-2022 走看看