BZOJ 4078: [Wf2014]Metal Processing Plant
4078: [Wf2014]Metal Processing Plant
Time Limit: 100 Sec Memory Limit: 128 MB
Submit: 86 Solved: 20
[Submit][Status][Discuss]
Description
定义集合S的价值D(S)为:
Input
输入数据的第一行是一个整数n,代表元素个数。
Output
输出只有一行,一个整数,代表min{D(A)+D(B)}。
Sample Input
4 5 0 2
1 3 7
2 0
4
Sample Output
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的更多相关文章
- BZOJ 4078: [Wf2014]Metal Processing Plant [放弃了]
以后再也不做$World Final$的题了................ 还我下午 bzoj上TLE一次后就不敢交了然后去uva交 Claris太神了代码完全看不懂 还有一个代码uva上竟然WA了 ...
- 【刷题】BZOJ 4078 [Wf2014]Metal Processing Plant
Description 定义集合S的价值D(S)为: 现在给你n个元素,并给出其中任意两个元素之间的d(i,j)值 要你将这些元素划分成两个集合A.B. 求min{D(A)+D(B)}. 注:d(i, ...
- bzoj 4078: [Wf2014]Metal Processing Plant【二分+2-SAT+枚举+并查集】
枚举从大到小s1,二分s2(越大越有可能符合),2-SAT判断,ans取min 思路倒是挺简单的,就是二分的时候出了比较诡异的问题,只能二分s2的值,不能在数组上二分... 有个优化,就是当不是二分图 ...
- BZOJ4078 : [Wf2014]Metal Processing Plant
设$D(A)\leq D(B)$,从小到大枚举$D(A)$,双指针从大到小枚举$D(B)$. 那么对于权值不超过$D(A)$的边,可以忽略. 对于权值介于$(D(A),D(B)]$之间的边,需要满足那 ...
- Codeforces Gym 101221G Metal Processing Plant(2-SAT)
题目链接 题意:有 \(n\) 个元素,第 \(i\) 个数与第 \(j\) 个数之间有一个权值 \(d_{i,j}\),\(d(i,j)=d(j,i)\). 定义函数 \(D(S)=\max\lim ...
- BZOJ4078 WF2014Metal Processing Plant(二分答案+2-SAT)
题面甚至没给范围,由数据可得n<=200.容易想到二分答案,暴力枚举某集合的价值,2-SATcheck一下即可.这样是O(n4logn)的. 2-SAT复杂度已经是下界,考虑如何优化枚举.稍微改 ...
- bzoj 4080: [Wf2014]Sensor Network【瞎搞+随机化】
参考:https://blog.csdn.net/YihAN_Z/article/details/73380387 一点都不想写正解.jpg random_shuffle一下然后贪心的加点,和ans取 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Processing Images
https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_ ...
随机推荐
- sql xml扩展字段 查询语句
[cms:sql query="SELECT ContentXML.value('/fields[1]/Address[1]','varchar(max)')AS valueForm FRO ...
- 【Effective C++读书笔记】序
C++ 是一个难学易用的语言! [C++为什么难学?] C++的难学,不仅在其广博的语法,以及语法背后的语义,以及语义背后的深层思维,以及深层思维背后的对象模型: C++的难学还在于它提供了四种不同而 ...
- C语言数组篇(二)指针数组和数组指针
数组指针 和 指针数组 这两个名词可以说是经常搞混了 数组指针--> 数组的指针 就是前面讲的 指向数组a的指针p; 指针数组--&g ...
- perl实现监控linux
1.使用root用户telnet进入linux系统 2.修改DNS以下两种方法 A.通过setup命令配置dns B.通过在/etc目录下创建resolv.conf文件 3.查看DNS是否配置成功 [ ...
- Android Stadio 导入moudle 不显示
Android Stadio 导入moudle 不显示,moudle 里面的java类也没有识别,只当是普通的txt文件. 后来,我发现,每个moudle 都有一个.iml 文件~ 然后我就随便翻翻配 ...
- 分别用反射、编程接口的方式创建DataFrame
1.通过反射的方式 使用反射来推断包含特定数据类型的RDD,这种方式代码比较少,简洁,只要你会知道元数据信息时什么样,就可以使用了 代码如下: import org.apache.spark.sql. ...
- Jenkins拾遗--第一篇(安装Jenkins)
起因 近期由于工作需要做起了起了jenkins的维护.不做不知道,一搞发现里边全是小坑.两个月弄了一身泥.曾经小瞧了它,但是发现其实要弄好它不是那么容易的.有句知名的话"没有总结就没有提高. ...
- 《Cracking the Coding Interview》——第1章:数组和字符串——题目4
2014-03-18 01:36 题目:给定一个字符串,将其中的空格‘ ’替换为‘%20’,你可以认为字符串尾部有足够空间来容纳新增字符.请不要额外开辟数组完成. 解法:先从前往后统计空格个数,然后从 ...
- 孤荷凌寒自学python第四天 安装python的其它IDE环境
孤荷凌寒自学python第四天 安装python的其它IDE环境 (完整学习过程屏幕记录视频地址在文末) 因为是完全的新手,对python环境搭建完全一无所知,因此,可真是大费周章才配置了其它多个Id ...
- 洛谷P1071潜伏者(提高组)
题目描述 R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动.历尽艰险后,潜伏于S国的R 国间谍小C终于摸清了 S 国军用密码的编码规则: 1. S国军方内部欲发送的原信息经过加密后在网 ...