二分+2-sat

枚举第一个权值,二分第二个权值,然后2-sat检查,当第一个权值已经不能形成二分图时,再往下没意义,因为没法分成两个点集。(双指针好像跑得慢)

#include<bits/stdc++.h>
using namespace std;
const int N = ;
struct edge {
int u, v, w;
edge(int u = , int v = , int w = ) : u(u), v(v), w(w) {}
bool friend operator < (edge A, edge B)
{
return A.w > B.w;
}
} e[N * N];
int n, tot, cnt, all, top, ans;
int dfn[N], low[N], st[N], belong[N], vis[N], Map[N][N], color[N], fa[N], d[N];
vector<int> G[N], g[N];
int find(int x)
{
if(fa[x] == x) return x;
int ret = find(fa[x]);
d[x] ^= d[fa[x]];
return fa[x] = ret;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++cnt;
st[++top] = u;
vis[u] = ;
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(vis[v]) low[u] = min(low[u], low[v]);
}
if(low[u] == dfn[u])
{
++all;
int j;
while()
{
j = st[top];
belong[j] = all;
vis[j] = ;
--top;
if(j == u) break;
}
}
}
bool check(int x, int y)
{
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(vis, , sizeof(vis));
top = ;
cnt = ;
all = ;
if(x > y) swap(x, y);
for(int i = ; i <= * n; ++i)
G[i].clear();
for(int i = ; i <= tot; ++i)
{
if(e[i].w > y)
{
G[e[i].u].push_back(e[i].v + n);
G[e[i].v].push_back(e[i].u + n);
G[e[i].u + n].push_back(e[i].v);
G[e[i].v + n].push_back(e[i].u);
}
else if(e[i].w > x)
{
G[e[i].u].push_back(e[i].v + n);
G[e[i].v].push_back(e[i].u + n);
}
}
for(int i = ; i <= * n; ++i) if(!dfn[i]) tarjan(i);
for(int i = ; i <= n; ++i) if(belong[i] == belong[i + n]) return false;
return true;
}
int main()
{
scanf("%d", &n);
for(int i = ; i <= n; ++i) fa[i] = i;
for(int i = ; i < n; ++i)
for(int j = ; j <= n - i; ++j)
{
scanf("%d", &Map[i][i + j]);
e[++tot] = edge(i, i + j, Map[i][i + j]);
}
if(n == )
{
puts("");
return ;
}
++tot;
sort(e + , e + tot + );
ans = ;
int j = tot;
for(int i = ; i <= tot && i <= j; ++i)
{
while(j && !check(e[i].w, e[j].w)) --j;
int u = find(e[i].u), v = find(e[i].v);
if(u != v)
{
ans = min(ans, e[i].w + e[j].w);
d[u] = d[e[i].u] ^ d[e[i].v] ^ ;
fa[u] = v;
}
else if(d[e[i].u] == d[e[i].v])
{
ans = min(ans, e[i].w + e[j].w);
break;
}
}
printf("%d\n", ans);
return ;
}

bzoj4078的更多相关文章

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

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

  2. BZOJ4078 : [Wf2014]Metal Processing Plant

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

随机推荐

  1. JS——tab切换

    排它思想: 1.先让所有的元素恢复默认值 2.再让选中的元素赋专有的值 3.干掉所有人,剩下我一个 <!DOCTYPE html> <html> <head lang=& ...

  2. 4.用Redis Desktop Manager连接Redis(Windows)

    相比连接CentOS的Redis,在Windows中的操作简单得让人感动. 所以这里我们使用的服务器系统是Windows Server 2016 R2. 而Windows版本的Redis官方网站并没有 ...

  3. C# Request

    string type = Request["type"]; //值为null; //?type= 值为""; //?type=12 值为"12&qu ...

  4. 新建springcloud 找不到请求路径

    新建  启动类 controller   都不可以直接放在  java 目录下   否则启动失败

  5. (C/C++学习)13.C语言字符串处理函数(一)

    说明:字符串处理的函数很多,本文将例举经常遇到的一些函数加以说明. 一.字符串的输入输出 头文件:<stdio.h> 1.利用标准输出函数 printf() 来输出,将格式设置为 s% . ...

  6. web前端学习总结--HTML

    web三要素: 浏览器:向服务器发起请求,下载服务器中的网页(HTML),然后执行HTML显示出内容 服务器:接受浏览器的请求,发送相应的页面到浏览器 HTTP协议:浏览器与服务器的通讯协议. HTM ...

  7. https://github.com/MediaTek-Labs/linkit-smart-7688-feed编译失败

    mkdir -p /home/fly/workdir/LinkltSmart7688Duo-20170626/openwrt/dl/home/fly/workdir/LinkltSmart7688Du ...

  8. Android第三方开源下拉框:NiceSpinner

     Android第三方开源下拉框:NiceSpinner Android原生的下拉框Spinner基本上可以满足Android开发对于下拉选项的设计需求,但现在越来越流行的下拉框不满足于Andro ...

  9. mybatis源码阅读-执行器StatementHandle和ParameterHandler(五)

    StatementHandle 类图 各个实现类的作用 SimpleStatementHandler 用于使用Statement操作数据库(不会使用参数化查询?) PreparedStatementH ...

  10. poj 2831 次小生成树模板

    /*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值& ...