P3588 [POI2015]PUS

好题


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

提交:3次

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

题解:

类似差分约束的模型,(a<b ightarrow aleq b-1 ightarrow 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

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