[BZOJ 2801]POI2012 Minimalist Security
来源:互联网 发布:python 3.0 廖雪峰 编辑:程序博客网 时间:2024/04/29 20:59
首先不要被题目吓倒,这题你就做出大半了。
只有联通块内才会互相约束(废话)
扫描每一个联通块,找到一个起点,假设他的权值为x。
那么每个连出去的边的终点权值为 w-x 。也就是说每个点上一定为kx+b(其中k=1或-1)
也许每个点会被扫描到多次,分以下几种情况
1、k1==k2,若b1!=b2无解,若b1==b2.......没有影响,继续running
2、k1!=k2,那么我们可以算出x的值,把这个值带入算出连通块里的点的值,判断有无解即可。
如果扫描途中没有遇到什么意外(就是1、2的情况)那么利用么个点i的不等式连立不等式组0<=ki x+bi<=pi解出x的范围
注意解集是否为空集,这里也可能出现无解。
最后我们可以看到代价是x的一次函数,也就是说最值在边界出取得,判断一下就好了。
复杂度O(n+m)
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int Maxn=6000005, Max=500005;int node[Maxn],next[Maxn],a[Max],q[Max],x,y,z,n,m,l,r,tot,i;LL len[Maxn],dig[Max],w[Max],total,maxx,minx,cnt1,cnt2,dw,up,data,t;bool v[Max],flag;struct arr { int w,s; } d[Max],tmp;int read(){ char ch=getchar(); int ret=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') {ret=ret*10+ch-'0'; ch=getchar();} return ret;}void add(int x,int y,int z){ node[++tot]=y; next[tot]=a[x]; a[x]=tot; len[tot]=z; node[++tot]=x; next[tot]=a[y]; a[y]=tot; len[tot]=z;}bool Judge(int x){ for (q[l=r=1]=x,total=0;l<=r;l++){ v[q[l]]=1; if (dig[q[l]]<0 || dig[q[l]]>w[q[l]]) return 0; total+=(LL)w[q[l]]-dig[q[l]]; for (int i=a[q[l]];i;i=next[i]){ if (dig[node[i]]==-1) dig[ q[++r]=node[i] ]=len[i]-dig[ q[l] ]; else if (dig[q[l]]+dig[node[i]]!=len[i]) return 0; } } return 1;}void bfs(int x){ d[x].w=0; d[x].s=1; v[x]=1; for (q[l=r=1]=x,data=-1;l<=r;l++){ for (int i=a[q[l]];i;i=next[i]){ if (v[node[i]]){ tmp.w=len[i]-d[node[i]].w; tmp.s=(d[node[i]].s^1); if (tmp.s==d[q[l]].s){ if (tmp.w!=d[q[l]].w) {flag=0; break;} else continue; } else { if (tmp.s==0) t=-1; else t=1; if ( (d[q[l]].w-tmp.w)/t<0 ) {flag=0; break;} if ( ( (d[q[l]].w-tmp.w)/t )%2!=0 ) {flag=0; break;} else {data = (d[q[l]].w-tmp.w)/t/2; break;} } } else { d[node[i]].w=len[i]-d[q[l]].w; d[node[i]].s=(d[q[l]].s^1); v[q[++r]=node[i]]=1; } } if (flag==0 || data>=0) break; } if (data>=0){ dig[x]=data; if (Judge(x)){ minx+=total; maxx+=total; } else {flag=0;return;} return; } if (flag==0) return; dw=0; up=1000000000; for (int i=1;i<=r;i++){ tmp=d[q[i]]; if (tmp.s==1){ up=min(up,(LL)w[q[i]]-tmp.w); dw=max(dw,(LL)-tmp.w); } else{ up=min(up,(LL)tmp.w); dw=max(dw,(LL)tmp.w-w[q[i]]); } } if (up<dw){ flag=0; return; } cnt1=cnt2=0; for (int i=1;i<=r;i++){ if (d[q[i]].s==1){ cnt1+=(LL)w[q[i]]-(d[ q[i] ].w+dw); cnt2+=(LL)w[q[i]]-(d[ q[i] ].w+up); } else { cnt1+=(LL)w[q[i]]-(d[ q[i] ].w-dw); cnt2+=(LL)w[q[i]]-(d[ q[i] ].w-up); } } minx+=min(cnt1,cnt2); maxx+=max(cnt1,cnt2);}int main(){ freopen("bez.in","r",stdin); freopen("bez.out","w",stdout); //scanf("%d%d",&n,&m); n=read(); m=read(); for (i=1;i<=n;i++) w[i]=read(); //scanf("%d",&w[i]); for (i=1;i<=m;i++){ //scanf("%d%d%d",&x,&y,&z); x=read(); y=read(); z=read(); add(x,y,z); } memset(dig,-1,sizeof(dig)); for (i=1,flag=1;i<=n;i++) if (!v[i]){ bfs(i); if (flag==0) break; } if (flag==0) puts("NIE"); else printf("%I64d %I64d\n",minx,maxx); return 0;}
0 0
- [BZOJ 2801]POI2012 Minimalist Security
- BZOJ2801: [Poi2012]Minimalist Security
- BZOJ2801/POI2012 Minimalist Security
- BZOJ2801: [Poi2012]Minimalist Security
- wikioi 2584 Minimalist Security
- BZOJ 2789: [Poi2012]Letters
- [BZOJ 2790]POI2012 Distance
- [BZOJ 2789]POI2012 Letters
- [BZOJ 2791]POI2012 Rendezvous
- [BZOJ 2803]Poi2012 Prefixuffix
- BZOJ 2797 Poi2012 Squarks
- bzoj 2789: [Poi2012]Letters
- BZOJ 2788: [Poi2012]Festival
- BZOJ 2803: [Poi2012]Prefixuffix
- [Poi2012] bzoj 2788 Festival
- BZOJ 2789: [Poi2012]Letters
- bzoj 2802: [Poi2012]Warehouse Store
- [BZOJ 2796]POI2012 Fibonacci Representation
- 第14章-重载运算符与类型转换
- 结构型模式之Adapter模式
- 第十七周 项目5 处理时间日期(计算这是第几天或第几秒的问题)
- 设计模式之六大原则
- (5)rosservice与rosparam
- [BZOJ 2801]POI2012 Minimalist Security
- 有些打不开的国外网页
- android判断是否连接wifi和网络状态的判断
- 也谈学习
- linux中对SQLite3函数的封装
- Nginx一例 500 internal server ERROR问题的解决
- 也谈学习
- java中instanceof用法
- 杭电ACM2040亲和数