zoukankan      html  css  js  c++  java
  • codevs 3314 魔法森林

    传送门

    3314 魔法森林

     时间限制: 3 s
     空间限制: 256000 KB
     题目等级 : 大师 Master
     
    题目描述 Description

    为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。
    魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪就会对其发起攻击。幸运的是,在号节点住着两种守护精灵:A型守护精灵与B型守护精灵。小E可以借助它们的力量,达到自己的目的。
    只要小E带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无向图中的每一条边Ei包含两个权值Ai与Bi。若身上携带的A型守护精灵个数不少于Ai,且B型守护精灵个数不少于Bi,这条边上的妖怪就不会对通过这条边的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向小E发起攻击,他才能成功找到隐士。
    由于携带守护精灵是一件非常麻烦的事,小E想要知道,要能够成功拜访到隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为A型守护精灵的个数与B型守护精灵的个数之和。

    输入描述 Input Description

    第1行包含两个整数N,M,表示无向图共有N个节点,M条边。 接下来M行,第行包含4个正整数Xi,Yi,Ai,Bi,描述第i条无向边。其中Xi与Yi为该边两个端点的标号,Ai与Bi的含义如题所述。 注意数据中可能包含重边与自环。

    输出描述 Output Description

    输出一行一个整数:如果小E可以成功拜访到隐士,输出小E最少需要携带的守护精灵的总个数;如果无论如何小E都无法拜访到隐士,输出“-1”(不含引号)。

    样例输入 Sample Input

    4 5
    1 2 19 1
    2 3 8 12
    2 4 12 15
    1 3 17 8
    3 4 1 17

    样例输出 Sample Output

    32

    数据范围及提示 Data Size & Hint

    2<=n<=50000
    0<=m<=100000
    1<=ai,bi<=50000

    【题目大意】

    求一条路径上最大a和最大b的和最小(a,b为其每一条边的两个权值)

    【思路】

    动态加边+spfa 枚举a权值(首先按升序排序)spfa跑b权值(此时我们认为每条边的权值只有b)

    则用 当前加入a边的权值+spfa跑出的最大b值更新答案。(spfa不是跑最短路,是找最大b值)

    【code】

    sorry 95分代码QAQ 错误欢迎指出感激不尽orzz 改了个cmp函数将b按升序排列多了10分...读入优化写挂了...x*10...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int  M=0x3f3f3f3f;
    #define MM 100001
    int dis[MM],n,m,ans=M;
    struct Edge
    {
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[100000*2];
    struct Road
    {
        int x,y,a,b;
    }road[MM<<1];
    bool cmp(Road R,Road U)
    {
        if(R.a==U.a)return R.b<U.b;
        return R.a<U.a;
    }
    inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return f*x;
    }
    int sumedge,head[MM],x,y,inq[MM]; 
    inline int add(int x,int y,int z)
    {
        edge[++sumedge]=Edge(x,y,z,head[x]);
        return head[x]=sumedge;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=m;i++)
        {
            road[i].x=read();road[i].y=read();
            road[i].a=read();road[i].b=read();
        //    cout<<road[i].x<<" "<<road[i].y<<" "<<road[i].a<<" "<<road[i].b<<endl;
        }
        sort(road+1,road+m+1,cmp);
        queue <int> q;
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0;
        for(int i=1;i<=m;i++)
        {
        
            x=road[i].x;y=road[i].y;
            add(x,y,road[i].b);add(y,x,road[i].b);
            if(!inq[x]){q.push(x);inq[x]=1;}
            if(!inq[y]){q.push(y);inq[y]=1;}
            if(road[i].a==road[i-1].a&&road[i].b==road[i-1].b)continue;
            while(!q.empty())
            {
                int now=q.front();q.pop();
                inq[now]=0;
                for(int i=head[now];i;i=edge[i].nxt)
                {
                    int to=edge[i].y;
                    if(max(dis[now],edge[i].z)>=dis[to])continue;
                    dis[to]=max(dis[now],edge[i].z);
                    if(!inq[to])
                    {
                        inq[to]=1;
                        q.push(to);
                    }
                }
            }
            ans=min(ans,road[i].a+dis[n]);
        } 
        if(ans==M)printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    } 

     撒花~~~~~~~~~代码A了。。。加了一个判断自环

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int  M=0x3f3f3f3f;
    #define MM 100001
    int dis[MM],n,m,ans=M;
    struct Edge
    {
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[100000*2];
    struct Road
    {
        int x,y,a,b;
    }road[MM<<1];
    bool cmp(Road R,Road U)
    {
        if(R.a==U.a)return R.b<U.b;
        return R.a<U.a;
    }
    inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return f*x;
    }
    int sumedge,head[MM],x,y,inq[MM]; 
    inline int add(int x,int y,int z)
    {
        edge[++sumedge]=Edge(x,y,z,head[x]);
        return head[x]=sumedge;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=m;i++)
        {
            road[i].x=read();road[i].y=read();
            road[i].a=read();road[i].b=read();
        //    cout<<road[i].x<<" "<<road[i].y<<" "<<road[i].a<<" "<<road[i].b<<endl;
        }
        sort(road+1,road+m+1,cmp);
        queue <int> q;
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0;
        for(int i=1;i<=m;i++)
        {
        
            x=road[i].x;y=road[i].y;
            if(x==y)continue;
            add(x,y,road[i].b);add(y,x,road[i].b);
            if(!inq[x]){q.push(x);inq[x]=1;}
            if(!inq[y]){q.push(y);inq[y]=1;}
            if(road[i].a==road[i-1].a&&road[i].b==road[i-1].b)continue;
            while(!q.empty())
            {
                int now=q.front();q.pop();
                inq[now]=0;
                for(int i=head[now];i;i=edge[i].nxt)
                {
                    int to=edge[i].y;
                    if(max(dis[now],edge[i].z)>=dis[to])continue;
                    dis[to]=max(dis[now],edge[i].z);
                    if(!inq[to])
                    {
                        inq[to]=1;
                        q.push(to);
                    }
                }
            }
           // cout<<road[i].a<<" "<<dis[n]<<endl;
            ans=min(ans,road[i].a+dis[n]);
        } 
        if(ans==M)printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    } 
  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/zzyh/p/6946314.html
Copyright © 2011-2022 走看看