zoukankan      html  css  js  c++  java
  • 洛谷 P1084 疫情控制 —— 二分+码力

    题目:https://www.luogu.org/problemnew/show/P1084

    5个月前曾经写过一次,某个上学日的深夜,精疲力竭后只有区区10分,从此没管...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    using namespace std;
    priority_queue< pair<int,int> >q1,q2;
    int const MAXN=50005;
    int n,m,head[MAXN],ct,ans,fa[MAXN],sid[MAXN],lf,lef[MAXN],gr[MAXN];
    ll l,r;
    bool vis[MAXN],in[MAXN];
    struct N{
        int to,next,w;
        N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {}
    }edge[MAXN<<1];
    struct E{
        int st,pos;
        ll rest;
    }am[MAXN];
    void add(int x,int y,int z)
    {
        edge[++ct]=N(y,head[x],z);head[x]=ct;
        edge[++ct]=N(x,head[y],z);head[y]=ct;
    }
    void ps(int x)
    {
        int nw=am[x].st;
        while(fa[nw]!=1&&am[x].rest-sid[nw])
        {
            am[x].rest-=sid[nw];
            nw=fa[nw];
        }
        if(fa[nw]==1&&am[x].rest>=2*sid[nw])am[x].pos=1,am[x].rest-=sid[nw];
        else am[x].pos=nw;
    }
    void init(int x,int f,int g,int w)//fa,gr,lef,sid
    {
        int t=0;
        fa[x]=f;sid[x]=w;
        if(g==1)gr[x]=x;
        else gr[x]=g;
        for(int i=head[x],u;i;i=edge[i].next)
        {
            u=edge[i].to;
            if(u==f)continue;
            init(u,x,gr[x],edge[i].w);t++;
        }
        if(!t)lef[++lf]=x;
    }
    void dfs(int x)
    {
        vis[x]=1;
        for(int i=head[x],u;i;i=edge[i].next)
            if(edge[i].to!=fa[x])dfs(edge[i].to);
    }
    bool pd(ll mid)
    {
    //    printf("mid=%d
    ",mid);
        memset(vis,0,sizeof vis);
        memset(in,0,sizeof in);
        while(q1.size())q1.pop();
        while(q2.size())q2.pop();
        for(int i=1;i<=m;i++)
        {
            am[i].rest=mid;
            ps(i);
            if(am[i].pos!=1)dfs(am[i].pos);
            q1.push(make_pair(-am[i].rest,i));
        }
    //    for(int i=1;i<=m;i++)
    //        printf("am[%d].pos=%d
    ",i,am[i].pos);
        for(int i=1;i<=lf;i++)
            if(!vis[lef[i]]&&!in[gr[lef[i]]])
            {
                q2.push(make_pair(-sid[gr[lef[i]]],gr[lef[i]]));
                in[gr[lef[i]]]=1;
            }
    //    printf("q1:%d q2:%d
    ",q1.size(),q2.size());
        while(q1.size()&&q2.size())
        {
            int x=q1.top().second;q1.pop();//am
            int y=q2.top().second;q2.pop();//gr
    //        printf("x=%d y=%d
    ",x,y);
            while(am[x].rest<sid[gr[y]]&&q1.size())x=q1.top().second,q1.pop();
            if(am[x].rest<sid[gr[y]]&&!q1.size())return 0;
        }
        
        if(q2.size())return 0;
        else return 1;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1,x,y,z;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);r+=z;
        }
        init(1,0,1,0);
    //    for(int i=1;i<=lf;i++)
    //        printf("lef[%d]=%d
    ",i,lef[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&am[i].st);
        ans=-1;
        while(l<=r)
        {
            ll mid=((l+r)>>1);
    //        cout<<ans<<endl;
            if(pd(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
    囧1

    这几天又重新写它了,自信码力已和当时不可同日而语,于是又写了一遍,然而仅仅20分,改了改成了30分...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    int const xn=50005;
    int n,m,cnt,hd[xn],ct,to[xn<<1],nxt[xn<<1],w[xn<<1],rs[xn],lf[xn],rk[xn];
    int f[xn][20],son[xn],dep[xn],num[xn];
    ll dis[xn],sum,ans;
    bool vis[xn],use[xn];
    priority_queue<int>q;
    vector<int>v[xn];
    struct N{
        int st,pos; ll tim;
        bool operator < (const N &y) const
            {return tim<y.tim;}
    }a[xn];
    int rd()
    {
        int ret=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return f?ret:-ret;
    }
    void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
    int dfs(int x,int fa,int r)
    {
        int ret=0,fl=0; f[x][0]=fa; 
        for(int i=1;i<=16;i++)f[x][i]=f[f[x][i-1]][i-1];
        for(int i=hd[x],u;i;i=nxt[i])
        {
            if((u=to[i])==fa)continue;
            fl=1;
            dis[u]=dis[x]+w[i]; dep[u]=dep[x]+1;
            if(x==1)lf[u]+=dfs(u,x,u),son[++cnt]=u;
            else ret+=dfs(u,x,r);
        }
        if(!fl)ret=1,rs[x]=r;
        return ret;
    }
    bool cmp(int a,int b){return dis[son[a]]>dis[son[b]];}
    void dfs2(int x)
    {
        bool fl=0;
        for(int i=hd[x],u;i;i=nxt[i])
            if((u=to[i])!=f[x][0])fl=1,dfs2(u);
        if(!fl)num[rs[x]]++;
    }
    bool ck(int mid)
    {
        memset(vis,0,sizeof vis);
        memset(num,0,sizeof num);
        memset(use,0,sizeof use);
        for(int i=1;i<=cnt;i++)v[i].clear();
        while(q.size())q.pop();
        for(int i=1;i<=m;i++)a[i].pos=0;
        for(int i=1;i<=m;i++)
        {
            int x=a[i].st; ll ret=mid;
            for(int j=16;j>=0;j--)
                if(f[x][j]>1&&dis[x]-dis[f[x][j]]<=ret)
                    ret-=dis[x]-dis[f[x][j]],x=f[x][j];
            if(dep[x]>1||(dep[x]==1&&ret<dis[x]))dfs2(x);
            else
            {
                a[i].pos=x; a[i].tim=ret-dis[x];
                q.push(i); //x:1~n
                v[x].push_back(i);
    //            printf("in:%d
    ",i);//tim从大到小
            }
        }
        for(int i=1;i<=cnt;i++)
            if(num[son[i]]==lf[son[i]])vis[i]=1;//i != son[i]   // vis[1~cnt]
        for(int i=1;i<=cnt;i++)
        {
            int x=rk[i];//1~cnt
    //        printf("vis[%d]=%d
    ",son[x],vis[x]);
            if(vis[x])continue;
            if(!q.size())return 0;
            int k=q.top(); q.pop();
            while(use[k])k=q.top(),q.pop();
            if(a[k].tim<dis[son[x]])
            {
                int us=-1;
                for(int j=0;j<v[son[x]].size();j++)
                {
                    int nw=v[son[x]][j];
                    if(!use[nw]&&(us==-1||a[nw].tim<a[us].tim))us=nw;
                }
                if(us==-1)return 0;
                else use[us]=1,q.push(k);
            }
            vis[x]=1;
    //        printf("%d -> %d
    ",i,son[x]);
        }
    //    printf("return 1
    ");
        return 1;
    }
    int main()
    {
        n=rd();
        for(int i=1,x,y,z;i<n;i++)
        {
            x=rd(); y=rd(); z=rd();
            add(x,y,z); add(y,x,z);
            sum+=z;
        }
        m=rd();
        for(int i=1;i<=m;i++)a[i].st=rd();
        dfs(1,0,0);
        for(int i=1;i<=cnt;i++)rk[i]=i;
        sort(rk+1,rk+cnt+1,cmp);//rk -> 1~cnt
    //    for(int i=1;i<=cnt;i++)printf("dis[%d]=%lld rk[%d]=%d
    ",son[i],dis[son[i]],i,rk[i]);
        ll l=0,r=sum; ans=-1;
        while(l<=r)
        {
            ll mid=((l+r)>>1ll);
    //        printf("l=%lld r=%lld mid=%lld
    ",l,r,mid);
            if(ck(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    囧2

    然后又去参考了TJ...看到思路和我的一样,但是代码简洁很多...

    于是改改改,然后和模仿的那篇TJ拍拍拍,居然拍出了TJ的错...又和另一篇TJ拍拍拍,大数据又有错...

    不管了直接交上去,就A了...

    然后发现数据生成没管军队不在根上,但第一篇TJ小数据真的错了...

    和 Narh 的代码拍,大数据又有错...但是数据那么大怎么改...不管了(反正也A了)...

    又练习码力了,没事不要多写什么 queue 啦, vector 啦,直接排个序就好了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=50005;
    int n,m,hd[xn],ct,to[xn<<1],nxt[xn<<1],w[xn<<1],dis[xn],sum,ans;
    int f[xn][20],num[xn],mn[xn],cnta,cnts,st[xn];
    bool vis[xn],use[xn];
    struct N{
        int id,tim;
        bool operator < (const N &y) const
            {return tim>y.tim;}
    }a[xn],son[xn];
    int rd()
    {
        int ret=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return f?ret:-ret;
    }
    void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
    void dfs(int x,int fa,int r)
    {
        int ret=0; f[x][0]=fa; 
        for(int i=1;i<=16;i++)f[x][i]=f[f[x][i-1]][i-1];
        for(int i=hd[x],u;i;i=nxt[i])
        {
            if((u=to[i])==fa)continue;
            dis[u]=dis[x]+w[i];    dfs(u,x,r);
        }
    }
    bool dfs2(int x)
    {
        bool fl=1,bj=1;
        if(vis[x])return 1;
        for(int i=hd[x],u;i;i=nxt[i])
        {
            if((u=to[i])==f[x][0])continue; bj=0;
            bool k=dfs2(u);
            if(!k)
            {
                fl=0;
                if(x==1)son[++cnts].id=u,son[cnts].tim=dis[u];
            }
        }
        if(bj)return 0;
        return fl;
    }
    bool ck(int mid)
    {
        memset(vis,0,sizeof vis);
        memset(use,0,sizeof use);
        memset(mn,0,sizeof mn);
        cnta=0; cnts=0;
        for(int i=1;i<=m;i++)
        {
            int x=st[i]; ll ret=mid;
            for(int j=16;j>=0;j--)
                if(f[x][j]>1&&dis[x]-dis[f[x][j]]<=ret)
                    ret-=dis[x]-dis[f[x][j]],x=f[x][j];
            if(f[x][0]>1||(f[x][0]==1&&ret<dis[x]))vis[x]=1;
            else
            {
                a[++cnta].id=i; a[cnta].tim=ret-dis[x];//-dis[x]
                if(!mn[x]||a[cnta].tim<a[mn[x]].tim)mn[x]=i;//mn[1~n]=(1~m)
            }
        }
        if(dfs2(1))return 1;
        sort(a+1,a+cnta+1); sort(son+1,son+cnts+1);
        for(int i=1,p=1;i<=cnts;i++)
        {
            int nw=son[i].id;
            if(mn[nw]&&!use[mn[nw]]){use[mn[nw]]=1; continue;}//优先用小的,不用考虑其它儿子是因为从大往小用
            while(p<=cnta&&use[a[p].id])p++;
            if(p>cnta||a[p].tim<son[i].tim)return 0;
            use[a[p].id]=1;
        }
        return 1;
    }
    int main()
    {
        n=rd();
        for(int i=1,x,y,z;i<n;i++)
        {
            x=rd(); y=rd(); z=rd();
            add(x,y,z); add(y,x,z);
            sum+=z;
        }
        m=rd();
        for(int i=1;i<=m;i++)st[i]=rd();
        dfs(1,0,0);
        int l=0,r=sum; ans=-1;
        while(l<=r)
        {
            int mid=((l+r)>>1ll);
            if(ck(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    zookeeper使用场景
    zookeeper安装配置
    hadoop 远程调试
    deep learning笔记
    Sentiment Analysis(1)-Dependency Tree-based Sentiment Classification using CRFs with Hidden Variables
    PRML阅读笔记 introduction
    Python 学习笔记(2)
    python nltk 学习笔记(5) Learning to Classify Text
    python nltk 学习笔记(4) Writing Structured Programs
    python nltk 学习笔记(3) processing raw text
  • 原文地址:https://www.cnblogs.com/Zinn/p/9690031.html
Copyright © 2011-2022 走看看