4078: [Wf2014]Metal Processing Plant

Time Limit: 100 Sec  Memory Limit: 128 MB
Submit: 86  Solved: 20
[Submit][Status][Discuss]

Description

定义集合S的价值D(S)为:

 
现在给你n个元素,并给出其中任意两个元素之间的d(i,j)值,要你将这些元素划分成两个集合A、B。求min{D(A)+D(B)}。
注:d(i,j)=d(j,i)。

Input

输入数据的第一行是一个整数n,代表元素个数。

之后n-1行描述的是d(i,j),这部分里,第i行包含n-i个整数,第i行第j列的整数代表的是d(i,i+j)。

Output

输出只有一行,一个整数,代表min{D(A)+D(B)}。

Sample Input

5
4 5 0 2
1 3 7
2 0
4

Sample Output

4

HINT

Source

分析:

貌似TLE了两个下午QAQ...

考虑最暴力的方法,枚举$s1$和$s2$的最大值,然后判断是否合法,判断的时候就是一个$2-SAT$问题,然后发现貌似$s1$确定的时候$s2$具有单调性,可以二分,然而复杂度还是很大...

所以考虑剪枝(貌似也可以用什么压位算法...然而不想学...),我们从大到小枚举$s1$,然后把不合法的边都连起来,发现如果不是一个二分图了,那么就可以停止枚举了...

貌似玄学复杂度...感觉这个剪枝很机智...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ctime>
//by NeighThorn
#define inf 0x3f3f3f3f
using namespace std; const int maxn=400+5,maxm=200000+5; int id;
int lala,fa[maxn],co[maxn];
int C,tim,top,mp[maxn],dfn[maxn],low[maxn],stk[maxm],instk[maxn];
int n,s1,s2,ans,cnt,len,w[maxn][maxn],hd[maxn],to[maxm],nxt[maxm]; struct M{ int x,y,v; inline M(){}; M(int a,int b,int c){
x=a,y=b,v=c;
} friend bool operator < (M a,M b){
if(a.v!=b.v)
return a.v>b.v;
if(a.x!=b.x)
return a.x>b.x;
return a.y>b.y;
} }e[maxm]; inline int read(void){
char ch=getchar();int x=0;
while(!(ch>='0'&&ch<='9')) ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
} inline void add(int x,int y){
to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
} inline void tarjan(int x){
low[x]=dfn[x]=++tim;stk[++top]=x;instk[x]=1;
for(int i=hd[x];i!=-1;i=nxt[i]){
if(!dfn[to[i]])
tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
else if(instk[to[i]])
low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x]){
C++;int tmp;
do{
tmp=stk[top--],instk[tmp]=0;mp[tmp]=C;
}while(tmp!=x);
}
} inline bool check(void){
cnt=C=tim=top=0;
memset(mp,0,sizeof(mp));
memset(hd,-1,sizeof(hd));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(instk,0,sizeof(instk));
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++){
if(w[i][j]>s1)
add(i<<1,j<<1|1),add(j<<1,i<<1|1);
if(w[i][j]>s2)
add(i<<1|1,j<<1),add(j<<1|1,i<<1);
}
for(int i=2;i<=(n<<1|1);i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
if(mp[i<<1]==mp[i<<1|1])
return false;
return true;
} inline int find(int x){
if(fa[x]==x)
return x;
int fx=find(fa[x]);
co[x]^=co[fa[x]];
return fa[x]=fx;
} inline int calc(int x){
int l=0,r=x,res=-1;
while(l<=r){
int mid=(l+r)>>1;s2=mid;
if(check())
r=mid-1,res=mid;
else
l=mid+1;
}
return res;
} signed main(void){
n=read();ans=inf;
if(n<=2) return puts("0"),0;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
w[i][j]=w[j][i]=read(),e[++lala]=M(i,j,w[i][j]);
sort(e+1,e+lala+1);for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1,x,y,fx,fy,res;i<=lala;i++){
s1=e[i].v;x=e[i].x,y=e[i].y,fx=find(x),fy=find(y);
if(fx!=fy){
res=calc(s1);
if(res!=-1) ans=min(ans,s1+res);
co[fx]=co[x]^co[y]^1;fa[fx]=fy;
}
else if(co[x]==co[y]){
res=calc(s1);
if(res!=-1) ans=min(ans,res+s1);
break;
}
}
printf("%d\n",ans);
return 0;
}

By NeighThorn

BZOJ 4078: [Wf2014]Metal Processing Plant的更多相关文章

  1. BZOJ 4078: [Wf2014]Metal Processing Plant [放弃了]

    以后再也不做$World Final$的题了................ 还我下午 bzoj上TLE一次后就不敢交了然后去uva交 Claris太神了代码完全看不懂 还有一个代码uva上竟然WA了 ...

  2. 【刷题】BZOJ 4078 [Wf2014]Metal Processing Plant

    Description 定义集合S的价值D(S)为: 现在给你n个元素,并给出其中任意两个元素之间的d(i,j)值 要你将这些元素划分成两个集合A.B. 求min{D(A)+D(B)}. 注:d(i, ...

  3. bzoj 4078: [Wf2014]Metal Processing Plant【二分+2-SAT+枚举+并查集】

    枚举从大到小s1,二分s2(越大越有可能符合),2-SAT判断,ans取min 思路倒是挺简单的,就是二分的时候出了比较诡异的问题,只能二分s2的值,不能在数组上二分... 有个优化,就是当不是二分图 ...

  4. BZOJ4078 : [Wf2014]Metal Processing Plant

    设$D(A)\leq D(B)$,从小到大枚举$D(A)$,双指针从大到小枚举$D(B)$. 那么对于权值不超过$D(A)$的边,可以忽略. 对于权值介于$(D(A),D(B)]$之间的边,需要满足那 ...

  5. Codeforces Gym 101221G Metal Processing Plant(2-SAT)

    题目链接 题意:有 \(n\) 个元素,第 \(i\) 个数与第 \(j\) 个数之间有一个权值 \(d_{i,j}\),\(d(i,j)=d(j,i)\). 定义函数 \(D(S)=\max\lim ...

  6. BZOJ4078 WF2014Metal Processing Plant(二分答案+2-SAT)

    题面甚至没给范围,由数据可得n<=200.容易想到二分答案,暴力枚举某集合的价值,2-SATcheck一下即可.这样是O(n4logn)的. 2-SAT复杂度已经是下界,考虑如何优化枚举.稍微改 ...

  7. bzoj 4080: [Wf2014]Sensor Network【瞎搞+随机化】

    参考:https://blog.csdn.net/YihAN_Z/article/details/73380387 一点都不想写正解.jpg random_shuffle一下然后贪心的加点,和ans取 ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. Processing Images

    https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_ ...

随机推荐

  1. 中通快递股份有限公司.net高级面试题

    中通快递分布式技术开发   gc垃圾回收原理 .net中,托管代码的内存管理是自动的,由GC进行管理,而对于非托管代码,则需要.net手动处理 CLR运行时,内存分为:托管堆和栈,其中栈用于存储值类型 ...

  2. 爬取多个url页面数据--手动实现

    # -*- coding: utf-8 -*- import scrapy from qiubaiByPages.items import QiubaibypagesItem class Qiubai ...

  3. POJ:1995-Raising Modulo Numbers(快速幂)

    Raising Modulo Numbers Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9512 Accepted: 578 ...

  4. zeppelin的数据集的优化

    前面我们介绍了zeppelin的修改,前面由于自己的原因,对zeppelin的修改过于多,现在由于优化了,我们两个类, 一个是zeppelin-server的NotebookServer的类的broa ...

  5. mt_vqmon异常数据分析

    mt_vqmon异常数据分析 1.首缓冲时间值异常(1) 分析:当第一个m3u8请求时,已经记录request时间,1423716972224, 正常情况会立即请求分片列表. 上述图表明请求了一个m3 ...

  6. Web 开发的未来:React、Falcor 和 ES6

    Web 开发的未来:React.Falcor 和 ES6 Widen是一家数字资产管理解决方案提供商.目前,其技术栈还非常传统,包括服务器端的Java.浏览器端的AngularJS.提供REST AP ...

  7. X的N次方。N比较大。

    final static long DIV = 1000000009; //分治法, 注意java类型为long, C++为__int64或 long long public static long ...

  8. gulp相关

    'use strict'; var gulp = require('gulp'), webserver = require('gulp-webserver'), //gulp服务器 connect = ...

  9. 玩转Linux之内存管理-free

    玩转Linux之内存管理-free free命令可以显示Linux系统中空闲的.已用的物理内存及swap内存,及被内核使用的buffer.在Linux系统监控的工具中,free命令是最经常使用的命令之 ...

  10. 如何自己编译apue.3e中代码 & 学习写makefile

    本来是搜pthread的相关资料,看blog发现很多linux程序员都看的一本神书<APUE>,里面有系统的两章内容专门讲pthread(不过是用c语言做的代码示例,这个不碍事,还是归到原 ...