首页 > 其他 > 详细

P3588 [POI2015]PUS

时间:2019-10-17 14:23:06      阅读:53      评论:0      收藏:0      [点我收藏+]

好题


思路:线段树优化建图+拓扑DP or 差分约束(都差不多);

提交:3次

错因:眼瞎没看题,Inf写的0x3f3f3f3f

题解:

类似差分约束的模型,\(a<b\rightarrow a\leq b-1 \rightarrow b\)\(a\) 连一条权值为 \(-1\) 的边,跑类似最短路的DP。
还是想一下之前的总结,我们发现,边权是非正的,并且0边没有形成环,所以一旦有环一定是负环,原问题无解,所以我们可以用拓扑排序去DP解这道题。
\(d[v]=min(d[v],d[u]+w[i])\),我们将所有没有确定的值均设成 \(1e9\) (题目中要求的上界),按照DP的式子,我们跑出来的是每个点的最大值(经过最少的边),若我们发现确定的值被更新的更小了,也是无解。否则有解,直接输出 \(d\) 数组即可。

代码:

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
namespace Luitaryi {
inline ll g() { register ll x=0,f=1;
    register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=500010,Y=6,F=20,Inf=1e9;
int n,m,s,rt[2],tot,cnt;
int ls[N*Y],rs[N*Y]; bool flg[N*Y];
int vr[N*F],nxt[N*F],fir[N*Y],in[N*Y],w[N*F],d[N*Y];
inline void add(int u,int v,int ww) 
    {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww,++in[v];}
inline void build(int& tr,int l,int r,const int& op) {
    if(l==r) return void(tr=l); tr=++tot; R md=l+r>>1;
    build(ls[tr],l,md,op),build(rs[tr],md+1,r,op);
    (op)?(add(ls[tr],tr,0),add(rs[tr],tr,0))
            :(add(tr,ls[tr],0),add(tr,rs[tr],0));
}
inline void change(int tr,int l,int r,int LL,int RR,const int& op) {
    if(LL<=l&&r<=RR) return void((op)?(add(tr,tot,0)):(add(tot,tr,-1))); 
    R md=l+r>>1; if(LL<=md) change(ls[tr],l,md,LL,RR,op); 
    if(RR>md) change(rs[tr],md+1,r,LL,RR,op);
}
inline void topo() { queue<int> q;
    for(R i=1;i<=tot;++i) if(!flg[i]) d[i]=Inf;
    for(R i=1;i<=tot;++i) if(!in[i]) q.push(i);
    while(q.size()) { R u=q.front(); q.pop();
        for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
            if(d[v]>d[u]+w[i]) {
                if(flg[v]) {return void(puts("NIE"));}
                d[v]=d[u]+w[i];
            } if(!--in[v]) q.push(v);
        }
    }   for(R i=1;i<=n;++i) if(in[i]||d[i]<=0) return void(puts("NIE"));
    puts("TAK"); for(R i=1;i<=n;++i) printf("%lld ",d[i]);
}
inline void main() {
    n=g(),s=g(),m=g(); tot=n;
    for(R i=1,u,w;i<=s;++i) u=g(),d[u]=g(),flg[u]=true;
    build(rt[0],1,n,0),build(rt[1],1,n,1);
    for(R i=1,l,r,k,p;i<=m;++i) {
        p=l=g(),r=g(),k=g(); ++tot;
        for(R j=1,q;j<=k;++j) { 
            q=g(); if(q>l) change(rt[0],1,n,p,q-1,0); 
            p=q+1,change(rt[1],1,n,q,q,1); 
        } if(p<=r) change(rt[0],1,n,p,r,0);
    } topo();
}
} signed main() {Luitaryi::main(); return 0;}

2019.10.17
29

P3588 [POI2015]PUS

原文:https://www.cnblogs.com/Jackpei/p/11691478.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!