zoukankan      html  css  js  c++  java
  • P5663 加工零件

    P5663 加工零件

    题解

    暴力搜索

    搜索显然会TLE

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const int maxn=1e5+10;
    struct node{
        int to,nxt;
    }edge[maxn*2];
    int head[maxn],cnt=0;
    int n,m,q;
    bool vis[maxn];//节点i是否与1直接相连
    int son[1005][1005]; 
    int num[1005];
    
    void addedge(int u,int v)
    {
        edge[++cnt].to =v;edge[cnt].nxt =head[u];head[u]=cnt;
        edge[++cnt].to =u;edge[cnt].nxt =head[v];head[v]=cnt;
    }
    
    void dfs(int sum,int u)
    {
        if(sum<0) return;
        if(num[1]==0) return;
        for(int v,i=1;i<=son[u][0];i++){
            v=son[u][i];
            num[v]=min(num[v],sum);
            dfs(sum-1,v);
        }
    }
    
    int main()
    {
        n=read();m=read();q=read();
        vis[1]=1;
        for(int u,v,i=1;i<=m;i++){
            u=read();v=read();
            if(u==1) vis[v]=1;
            if(v==1) vis[u]=1;
            son[u][++son[u][0]]=v;
            son[v][++son[v][0]]=u;
            addedge(u,v);
            addedge(v,u);
        }
        for(int a,l,t=1;t<=q;t++){
            memset(num,63,sizeof(num));
            a=read();l=read();
            if(l==1){
                if(a==1||(!vis[a])) {
                    printf("No
    ");
                    continue;
                }
                else if(vis[a]&&a!=1) {
                    printf("Yes
    ");
                    continue;
                }
            }else{
                num[a]=l;
                dfs(l-1,a); 
                if(num[1]==0) printf("Yes
    ");
                else printf("No
    ");
            }
        }
        return 0;
    }
    暴力搜索 40pt

    考虑正解 SPFA最短路

    题目给出一张无向图,他大概长这个亚子

    对于给出一个点 a 要完成第  L  阶段任务,也就是从 a 到 1 找一条长度为 L 的路径 

    我们发现

    1.  点2到1的距离为1(奇数),如果2完成奇数阶段任务,那么1就要为它提供原料,如果是偶数阶段任务就不用

    2.  点5到点1的距离为2(偶数),如果5完成偶数阶段任务,那么1就要为它提供原料,如果是奇数阶段任务就不用

    如果2到1的距离是5,也就是大于他们之间最短距离,那么要完成的阶段就会在二者之间不断传递(2-->5  , 1-->4 , 2-->3  , 1-->2  , ....),最后会变成上面分析的情况1  

    也就是说

    1.  如果点a要完成的任务阶段数大于等于他们之间的最短距离,都可以化简成处理他们之间的最短距离来做

    2.  如果a要完成的任务阶段数本就小于他们之间的最短距离,也就是a在扩展到1之前就已经有别的点为它提供原料,1节点自然不用提供原料

    我们现在就要考虑上面说的第一种情况 L >= dis(a-->1)

    由于从一个节点出发到达1会有很多路径,我们用 dis[ i ][ 0 ] 记录从节点 i 到节点 的长度为偶数的最短路的长度,用 dis[ i ][ 1 ] 记录从节点 到节点 的长度为奇数最短路的长度,SPFA 具体实现

    更新数组的柿子也就是:

    dis[ v ][ 0 ] = min ( dis[ v ][ 0 ] , dis[ u ][ 1 ] + 1 )

    dis[ v ][ 1 ] = min ( dis[ v ][ 1 ] , dis[ u ][ 0 ] + 1 )

    综上分析得出结论

    1.  点 a 要完成的阶段任务数为偶数, 如果从a-->1存在一条偶数最短路,并且它的长度小于等于该任务数,1需要提供原料

    2.  点 a 要完成的阶段任务数为奇数, 如果从a-->1存在一条奇数最短路,并且它的长度小于等于该任务数,1需要提供原料

    3.  其余情况就不用1提供原料了

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const int maxn=1e5+10;
    int n,m,qus;
    
    struct node{
        int to,nxt;
    }edge[maxn<<1];
    int cnt=0,head[maxn];
    inline void addedge(int u,int v)
    {
        edge[++cnt].to =v,edge[cnt].nxt =head[u],head[u]=cnt;
        edge[++cnt].to =u,edge[cnt].nxt =head[v],head[v]=cnt;
    }
    
    int dis[maxn][2];
    bool vis[maxn];
    
    inline void spfa()
    {
        queue<int>q;
        memset(dis,63,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[1][0]=0;
        vis[1]=1;
        q.push(1);
        while(!q.empty() ){
            int u=q.front() ;
            q.pop() ;
            vis[u]=0;
            for(int v,i=head[u];i;i=edge[i].nxt ){
                v=edge[i].to ;
                if(dis[v][1]>dis[u][0]+1){
                    dis[v][1]=dis[u][0]+1;
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=1; 
                    }
                }
                if(dis[v][0]>dis[u][1]+1){
                    dis[v][0]=dis[u][1]+1;
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=1; 
                    }
                }
            }
        } 
    }
    
    int main()
    {
        n=read();m=read();qus=read();
        for(int u,v,i=1;i<=m;i++){
            u=read();v=read();
            addedge(u,v);
        }
        spfa();
        for(int a,l,i=1;i<=qus;i++){
            a=read();l=read();
            if((l%2)&&(dis[a][1]<=l))printf("Yes
    ");
            else if((l%2==0)&&(dis[a][0]<=l))printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    HDU 1116 Play on Words(并查集和欧拉回路)(有向图的欧拉回路)
    PHP 错误与异常 笔记与总结(8)自定义错误处理函数 set_error_handler()
    【VR】Leap Motion 官网文档 FingerModel (手指模型)
    2014年辛星解读Javascript之DOM之事件及其绑定
    java.util.logging.Logger使用具体解释
    技术走向管理一些思考(8)-适合的人才
    rac_grid自检提示缺少cvuqdisk包
    C++第15周(春)项目3
    交换a、b的值temp = a; a = b; b = temp;比a = a^b;b = a^b;a = a^b;快
    BZOJ 1089 SCOI2003 严格n元树 动态规划+高精度
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/12069136.html
Copyright © 2011-2022 走看看