二分+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. Gpupdate命令详解

    刷新本地和基于 Active Directory 的组策略设置,包括安全设置.该命令可以取代 secedit 命令中已经过时的 /refreshpolicy 选项. MS-DOS命令语法 gpupda ...

  2. POJ_3279_(dfs)(状态)

    ---恢复内容开始--- Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8219   Accepted:  ...

  3. get传数组

    开发真的处处都是坑呀 ajax get请求,传数组,想当然的给了个json数组['','',''],结果500错误 正确的方式,多次赋值,见下图,后台会自动转数组

  4. Origin C调用NAG库

    NAG(Numerical Algorithms Group, www.nag.com)库是一个无与伦比的算法库,它提供的算法可靠.轻便.严谨,覆盖了数学与统计方方面面.最大的缺点就是:它是一个收费的 ...

  5. vsftpd:500OOPS:vsftpd:refusingtorunwithwritablerootinsidechroot()错误的解决方法

    当我们限定了用户不能跳出其主目录之后,使用该用户登录FTP时往往会遇到这个错误: 500 OOPS: vsftpd: refusing to run with writable root inside ...

  6. Linux 开启443端口

     1 在Linux终端输入指令: iptables -I INPUT -p tcp --dport 443 -j ACCEPT   2 回车之后继续输入指令,输入保存防火墙配置指令: service ...

  7. 【GC】

    using 语句适用于清理单个非托管资源的情况,而多个非托管对象的清理最好以 try-finnaly 来实现,因为嵌套的 using 语句可能存在隐藏的 Bug.内层 using 块引发异常时,将不能 ...

  8. Win32 线程同步

    Win32 线程同步 ## Win32线程同步 ### 1. 原子锁 ### 2. 临界区 {全局变量} CRITICAL_SECTION CS = {0}; // 定义并初始化临界区结构体变量 {线 ...

  9. java的四舍五入及取整

    四舍五入用 Math.round(double a): 向上取整用 Math.ceil(double a): 向下取整用 Math.floor(double a):

  10. 3、ceph-deploy之配置使用文件系统

    我们在admin节点执行下述操作,来配置使用ceph集群的文件系统 必备条件 1.在ceph-client节点安装ceph ceph-deploy install ceph-client 2.确认ce ...