0x65 负环与差分约束

· · 个人记录

Sightseeing Cows

```cpp #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=1e3+10,M=1e4+10; const double eps=1e-6; struct Edge{ int nxt,ver,w; }e[M]; int n,m,tot,hd[N],a[N],cnt[N]; double dis[N]; bool inq[N]; void add(int x,int y,int z){ tot++; e[tot].nxt=hd[x]; e[tot].ver=y; e[tot].w=z; hd[x]=tot; } bool Check(double mid){ queue<int>q; for(int i=1;i<=n;i++){ q.push(i); inq[i]=1; dis[i]=0,cnt[i]=0; } while(q.size()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=hd[u];i!=0;i=e[i].nxt){ int v=e[i].ver; double z=mid*e[i].w-a[v]; if(dis[v]>dis[u]+z){ dis[v]=dis[u]+z; if(!inq[v]){ cnt[v]++; inq[v]=1; q.push(v); } } if(cnt[v]>=n) return true; } } return false; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; int x,y,z; double l=0,r=0,mid; for(int i=1;i<=m;i++){ cin>>x>>y>>z; add(x,y,z); r+=z; } while(r-l>eps){ mid=(l+r)/2; if(Check(mid)) l=mid; else r=mid; } printf("%.2f",l); return 0; } ``` # Intervals 解法 $1$ :差分约束系统。建图跑最短路。 ```cpp #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=5e4+10,M=1e6+10; struct Edge{ int nxt,ver,w; }e[M]; int n,m,tot,hd[N],dis[N]; bool inq[N]; void add(int x,int y,int z){ tot++; e[tot].nxt=hd[x]; e[tot].ver=y; e[tot].w=z; hd[x]=tot; } void Spfa(){ queue<int>q; memset(dis,0x3f,sizeof(dis)); dis[m]=0; inq[m]=1; q.push(m); while(q.size()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=hd[u];i!=0;i=e[i].nxt){ int v=e[i].ver; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!inq[v]){ q.push(v); inq[v]=1; } } } } } int main(){ cin>>n; int x,y,z; for(int i=1;i<=n;i++){ cin>>x>>y>>z; x++,y++; m=max(m,y); add(y,x-1,-z); } for(int i=1;i<=m;i++){ add(i,i-1,0); add(i-1,i,1); } Spfa(); cout<<-dis[0]; return 0; } ``` 解法 $2$ :数据结构优化贪心。发现需要快速完成三种操作:区间查询,单点修改,查询当前位置之前第一个空闲位置。于是可以使用树状数组和并查集维护。 ```cpp #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=5e4+10; struct Node{ int l,r,cnt; }a[N]; int n,ans,fa[N],c[N]; bool vis[N]; bool cmp(Node x,Node y){ return x.r<y.r; } int lowbit(int x){ return x&(-x); } int Ask(int x){ if(!x) return 0; int res=0; for(;x>0;x-=lowbit(x)) res+=c[x]; return res; } void Add(int x){ for(;x<N;x+=lowbit(x)) c[x]++; } int Getfa(int x){ if(x==fa[x]) return x; return fa[x]=Getfa(fa[x]); } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].l>>a[i].r>>a[i].cnt; a[i].l++,a[i].r++; } sort(a+1,a+n+1,cmp); for(int i=0;i<N;i++) fa[i]=i; for(int i=1;i<=n;i++){ int x=a[i].cnt; x-=(Ask(a[i].r)-Ask(a[i].l-1)); int t=Getfa(a[i].r); while(x>0){ Add(t); x--,ans++; fa[t]=t-1; t=Getfa(t); } } cout<<ans; return 0; } ```