BZOJ2801/POI2012 Minimalist Security
来源:互联网 发布:戴尔公司待遇 知乎 编辑:程序博客网 时间:2024/05/17 01:55
Task
给出一个N个顶点、M条边的无向图,边(u,v)有权值w(u,v),顶点i也有权值p(i),
并且对于每条边(u,v)都满足p(u)+p(v)>=w(u,v)。
现在要将顶点i的权值减去z(i),其中0<=z(i)<=p(i)。
修改后设顶点i的权值p’(i)=p(i)-z(i),对于每条边(u,v)都满足p’(u)+p’(v)=w(u,v)。
求sum{z(i)}的最小值和最大值。
n<=500,000, m<=3,000,000, 0<=p(i)<=10^6, 0<=w<=10^6.
Solution
对于每一条边(u,v):z[u]+z[v]是确定的,也就是确定了端点中的一个,另一个也可以确定了.那么假如确定联通块内任意一点的值,整个联通块都可以确定下来了.
假设设联通块任意一点x的值为a,那么联通块剩下的点k都可以用来y*a+z表示.通过0≤y*a+z≤p[k]求出a的范围.对于这个联通块,求出∑z[k]关于a的表达式,利用a的范围求出最值.
只要遍历一遍图即可,复杂度O(m+n).
当然还有一种做法,通过并查集,维护每个点到它所在树根(假设树根的值为a)的表达式:ya+z.
每次对一条边(u,v):
假如u,v已经联通,可以直接求出a的值.
否则合并两棵树.
//对于并查集的做法,需要计算的地方有点多不易调试,比赛时最好选取第一种做法.
#include<cstdio>#include<cstring>#include<algorithm>#define ll long long#include<iostream>using namespace std;const int M=5e5+5;int head[M],rt,ec=0,f[M],n,p[M],flag=1,tot,A=0,m;ll val[M];ll mx=0,mi=0,L,R,B=0;struct node{ int to,v,nex;}e[M*12];inline void rd(int &res){ res=0;char c; while(c=getchar(),c<48); do res=(res<<1)+(res<<3)+(c^48); while(c=getchar(),c>=48);}void ins(int a,int b,int c){ e[ec]=(node){b,c,head[a]}; head[a]=ec++; e[ec]=(node){a,c,head[b]}; head[b]=ec++; }bool dfs(int x,int par){ ll a=(p[x]-val[x])/f[x],b=-val[x]/f[x]; //0<=f[x]*a+val[x]<=p[x] //a<=p[x]-val[x]/f[x] //a>=-val[x]/f[x] A+=f[x]; B+=val[x]; if(f[x]>0)L=max(L,b),R=min(R,a); else L=max(L,a),R=min(R,b); if(L>R)return false; for(int i=head[x];~i;i=e[i].nex){ int to=e[i].to,v=e[i].v;// if(to==par)continue; ll t=v-val[x]; if(f[to]!=0){ if(f[to]==-f[x]&&val[to]!=t)return false; else if(f[to]!=-f[x]){ if((val[to]-t)%(-f[x]-f[to])!=0)return false; ll res=(val[to]-t)/(-f[x]-f[to]); L=max(L,res);//f[to]+val[to]=f[x]+val[x] R=min(R,res); if(L>R)return false; } } else{ f[to]=-f[x]; val[to]=t; if(!dfs(to,x)){return false;} } } return true;}bool solve(){ for(int i=1;i<=n;i++){ if(f[i]==0){ L=-1e18,R=1e18; A=B=0; f[i]=1; val[i]=0; if(!dfs(i,i))return false; ll a=L*A+B,b=R*A+B; mi+=min(a,b); mx+=max(a,b); } } return true;}int main(){ memset(head,-1,sizeof(head)); int i,j,a,b,c; rd(n);rd(m); for(i=1;i<=n;i++)rd(p[i]); for(i=1;i<=m;i++){ rd(a);rd(b);rd(c); ins(a,b,p[a]+p[b]-c); } if(!solve())puts("NIE"); else cout<<mi<<" "<<mx<<endl; return 0;}
并查集:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<ctime>#include<cstdlib>#include<string>#include<cmath>#include<map>#include<set>#include<queue>#include<bitset>#define ll long long#define lsy puts("lay")#define rep(i,a,b) for((i)=(a);(i)<=(b);(i)++)#define per(i,a,b) for((i)=(b);(i)>=(a);(i)--)using namespace std;inline void rd(int &res){ res=0;char c; while(c=getchar(),c<48); do res=(res<<1)+(res<<3)+(c^48); while(c=getchar(),c>=48);}inline void print(int k){ if(!k)return; print(k/10); putchar(k%10^48);}inline void sc(int k){ if(k<0){k=-k;putchar('-');} print(k); if(k==0)putchar('0');// putchar('\n');}inline void Max(int &x,int y){if(x<y)x=y;}inline void Min(int &x,int y){if(x>y)x=y;}const int maxn=500005;const int maxm=3000005;int u[maxm],v[maxm],e[maxm],fa[maxn],f[maxn],n,m,h[maxn],p[maxn];ll mi=0,mx=0,sum[maxn],rt[maxn],val[maxn],l[maxn],r[maxn];int get(int x){ if(fa[x]!=x){ int a=f[x],b=fa[x]; fa[x]=get(fa[x]); val[x]=val[b]*a+val[x]; f[x]=f[b]*a; } return fa[x];}bool solve(){ int i,j,k,a,b,c; ll d,t; for(i=1;i<=m;i++){ a=get(u[i]),b=get(v[i]); if(a!=b){ val[b]=f[v[i]]*(-val[u[i]]+e[i]-val[v[i]]); f[b]=-f[u[i]]*f[v[i]]; fa[b]=a; if(~rt[b]){//rt[b]=rt[a]*f[b]+val[b] c=(rt[b]-val[b])*f[b]; if(~rt[a]&&rt[a]!=c) return false; rt[a]=c; } continue; } c=f[u[i]]+f[v[i]]; d=e[i]-(val[u[i]]+val[v[i]]);//c*rt=d if(c!=0&&d%c!=0){return false;} if(c){ t=d/c; if(rt[a]==-1)rt[a]=t; else if(rt[a]!=t){ return false; } } } for(i=1;i<=n;i++)l[i]=0,r[i]=p[i]; for(i=1;i<=n;i++){ a=get(i);//0<=f[i]*rt+val[i]<=p[i]' if(f[i]>0){//rt<=p[i]-val[i] r[a]=min(r[a],p[i]-val[i]); l[a]=max(l[a],-val[i]); } else {//0<=-rt+val[i]<=p[i] r[a]=min(r[a],val[i]); l[a]=max(l[a],val[i]-p[i]); } h[a]+=f[i]; sum[a]+=val[i]; } for(i=1;i<=n;i++){ if(fa[i]==i){ a=i; if(l[a]>r[a]){ return false; }if(~rt[a]){ if(rt[a]>r[a]||rt[a]<l[a]){ return false;} mi+=rt[a]*h[a]+sum[a],mx+=rt[a]*h[a]+sum[a]; } else { ll b=h[a]*l[a]+sum[a],c=h[a]*r[a]+sum[a]; mi+=min(b,c);mx+=max(b,c); } } } return true;}int main(){ int i,j,k; memset(rt,-1,sizeof(rt)); memset(val,0,sizeof(val)); rd(n);rd(m); for(i=1;i<=n;i++){ fa[i]=i,rd(p[i]); f[i]=1; } for(i=1;i<=m;i++){ rd(u[i]);rd(v[i]);rd(e[i]); e[i]=p[u[i]]+p[v[i]]-e[i]; } if(!solve())puts("NIE"); else cout<<mi<<" "<<mx<<endl; return 0;}
0 0
- BZOJ2801: [Poi2012]Minimalist Security
- BZOJ2801/POI2012 Minimalist Security
- BZOJ2801: [Poi2012]Minimalist Security
- [BZOJ 2801]POI2012 Minimalist Security
- wikioi 2584 Minimalist Security
- Minimalist GNU for Windows - MinGW
- MinGW - Minimalist GNU for Windows
- POI2012题解
- [Poi2012]Festival
- MinGW(Minimalist GNU for Windows)的安装
- MinGW —— Minimalist GNU for Windows
- Security
- security
- Security
- Security
- security
- Security
- Security
- 课堂笔记----JSP内置9大对象。
- 关于继承Fragment的事
- 欢迎使用CSDN-markdown编辑器
- Android TouchImage图片放大,缩小,点击还原,double点击放大 源码解析
- programming in lua 第四章笔记
- BZOJ2801/POI2012 Minimalist Security
- 【LeetCode】220. Contains Duplicate III
- easyui 标题和内容对齐,自适应
- codeforces732A A. Buy a Shovel
- 相比于深度学习,传统的机器学习算法难道就此没落了吗,还有必要去学习吗?
- 离屏绘制
- [游戏] chrome 的小彩蛋
- 283. Move Zeroes
- 快速排序算法