FJOI省队集训 florida
省队成员(大部分)都没来...像我这种沙茶天天写写玄学算法都能排在榜上面...果然正解写挂的人远比暴力拍对的人少啊...陆陆续续会补一些题解。(不过有些题太神了可能补不上题解
有n个物品,两个袋子A和B。若物品i与j放在同一个袋子里,那么代价为T[i][j],保证T[i][i]=0,T[i][j]=T[j][i]。
一个袋子的代价D=袋子中两两物品代价的最大值。你需要将物品分配到两个袋子中,最小化D(A)+D(B)。
2<=n<=250,0<=T[i][j]<=10^9。
陈旭大爷有一种暴力倍增的做法可以跑过去...跪烂
我们不妨设D(A)<=D(B),那么我们枚举D(B),显然可以二分D(A)判可行性。
对于两物品i,j,如果D(A)<T[i][j]<=D(B),那么i和j至少要有一个在B中。如果T[i][j]>D(b),那么i和j就不能放在一起。
所以这就成了一个2-sat问题,可以用经典的tarjan做法解决。
这样是O(n^4logn)的,由于过于玄学只能得到部分分。
这个做法看起来已经十分优秀了,要怎么优化呢?
我们发现枚举D(B)看起来就不太靠谱,真的要枚举O(n^2)种取值吗?
显然不要,我们考虑搞出一棵最大生成树,以T为边权。接下来考虑对这棵生成树黑白染色,如果一个集合B包括了两种颜色的点,那么显然D(B)就是最大生成树上的边(可以由kruskal算法的正确性得到)。否则B只包括一种颜色的点,只包含所有白点或只包含所有黑点(为什么是所有点呢?因为如果是部分点,那么A肯定包括另一种颜色的全部点。由于是最大生成树,那么D(A)>D(B))。所以我们只要尝试这些D(B)即可。
这样似乎就是O(n^3logn)的。
我们可以加一些奇技淫巧来优化,我的做法是将权值离散二分,然后每次根据最优解随便剪剪枝,这样就可以过了。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define SZ 666
int n,t[SZ][SZ],ls[SZ*SZ],ln=0,en=0;
int ff[SZ];
int gf(int x)
{
return ff[x]?ff[x]=gf(ff[x]):x;
}
int M=0,fst[SZ*SZ*5],vb[SZ*SZ*5],nxt[SZ*SZ*5];
void ad_de(int a,int b) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b;}
void adde(int a,int b) {ad_de(a,b); ad_de(b,a);}
struct edg {int x,y;}es[SZ*SZ];
bool operator < (edg a,edg b) {return t[a.x][a.y]>t[b.x][b.y];}
int ds[SZ*SZ],dn=0;
int col[SZ];
void dfs(int x,int c)
{
if(col[x]!=-1) return;
col[x]=c;
for(int e=fst[x];e;e=nxt[e]) dfs(vb[e],!c);
}
//tarjan
namespace TJ
{
int M=0,fst[SZ*SZ*5],nxt[SZ*SZ*5],vb[SZ*SZ*5];
void ad_de(int a,int b) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b;}
void adde(int a,int b) {ad_de(a,b); ad_de(b,a);}
int ss[SZ],sn=0,low[SZ],dfn[SZ],cnt=0,bl[SZ],scc=0;
bool ins[SZ];
void init()
{
M=sn=cnt=scc=0;
for(int i=1;i<=2*n+1;i++) fst[i]=low[i]=dfn[i]=bl[i]=ins[i]=0;
}
void tarjan(int x)
{
low[x]=dfn[x]=++cnt; ss[++sn]=x; ins[x]=1;
for(int e=fst[x];e;e=nxt[e])
{
int b=vb[e];
if(!dfn[b]) {tarjan(b); low[x]=min(low[x],low[b]);}
else if(ins[b]) low[x]=min(low[x],dfn[b]);
}
if(dfn[x]!=low[x]) return;
int p; ++scc;
do
{
p=ss[sn--]; ins[p]=0; bl[p]=scc;
}while(p!=x);
}
}
bool ok(int da,int db)
{
TJ::init();
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
int T=t[i][j];
if(T>db)
{
TJ::adde(i*2,j*2+1); TJ::adde(i*2+1,j*2);
}
else if(T>da)
{
TJ::ad_de(i*2,j*2+1); TJ::ad_de(j*2,i*2+1);
}
}
}
for(int i=2;i<=2*n+1;i++)
{
if(!TJ::dfn[i]) TJ::tarjan(i);
}
for(int i=1;i<=n;i++) if(TJ::bl[i*2]==TJ::bl[i*2+1]) return 0;
return 1;
}
struct F{F(string t){freopen((t+".in").c_str(),"r",stdin);freopen((t+".out").c_str(),"w",stdout);}}__
("florida");
int main()
{
memset(col,-1,sizeof(col));
M=dn=ln=en=0;
memset(fst,0,sizeof(fst));
memset(ff,0,sizeof(ff));
if(scanf("%d",&n)==EOF) return 0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++) scanf("%d",&t[i][j]), t[j][i]=t[i][j];
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++) if(t[i][j]) ls[++ln]=t[i][j];
}
sort(ls+1,ls+1+ln); ln=unique(ls+1,ls+1+ln)-ls-1;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++) es[++en].x=i, es[en].y=j;
}
sort(es+1,es+1+en);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) t[i][j]=lower_bound(ls,ls+1+ln,t[i][j])-ls;
}
for(int i=1;i<=en;i++)
{
int ga=gf(es[i].x),gb=gf(es[i].y);
if(ga==gb) continue;
ff[ga]=gb; ds[++dn]=t[es[i].x][es[i].y];
adde(es[i].x,es[i].y);
}
dfs(1,0);
int maxn[2]={0,0};
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(col[i]==col[j]) maxn[col[i]]=max(maxn[col[i]],t[i][j]);
}
}
ds[++dn]=maxn[0]; ds[++dn]=maxn[1];
sort(ds+1,ds+1+dn); dn=unique(ds+1,ds+1+dn)-ds-1;
int ans=2000000033;
for(int i=0;i<=dn;i++)
{
int db=ds[i],qaq=db;
while(qaq>=0&&ls[db]+ls[qaq]>=ans) --qaq;
if(qaq<0||!ok(qaq,db)) continue;
int l=0,r=qaq;
while(l!=r)
{
int mid=(l+r)>>1;
if(ok(mid,db)) r=mid; else l=mid+1;
}
ans=min(ans,ls[db]+ls[l]);
}
printf("%d\n",ans);
main();
}
FJOI省队集训 florida的更多相关文章
- FJOI省队集训 chessboard
(题目懒得打字了,建议到新窗口查看) 显然这玩意儿是可以按位搞的...然后就是一个裸的最小割模型? 然而这样做理论上只有30分实际上有40分. 事实上我们可以发现,每一列的取值只和上一列有关,这样我们 ...
- JS省队集训记
不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...
- [2018HN省队集训D9T1] circle
[2018HN省队集训D9T1] circle 题意 给定一个 \(n\) 个点的竞赛图并在其中钦定了 \(k\) 个点, 数据保证删去钦定的 \(k\) 个点后这个图没有环. 问在不删去钦定的这 \ ...
- [2018HN省队集训D8T1] 杀毒软件
[2018HN省队集训D8T1] 杀毒软件 题意 给定一个 \(m\) 个01串的字典以及一个长度为 \(n\) 的 01? 序列. 对这个序列进行 \(q\) 次操作, 修改某个位置的字符情况以及查 ...
- [2018HN省队集训D8T3] 水果拼盘
[2018HN省队集训D8T3] 水果拼盘 题意 给定 \(n\) 个集合, 每个集合包含 \([1,m]\) 中的一些整数, 在这些集合中随机选取 \(k\) 个集合, 求这 \(k\) 个集合的并 ...
- [2018HN省队集训D6T2] girls
[2018HN省队集训D6T2] girls 题意 给定一张 \(n\) 个点 \(m\) 条边的无向图, 求选三个不同结点并使它们两两不邻接的所有方案的权值和 \(\bmod 2^{64}\) 的值 ...
- [Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform
[Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform 题意 给定一个小写字母构成的字符串, 每个字符有一个非负权值. 输出所有满足权值和等于这个子串在所有本质 ...
- [2018HN省队集训D5T2] party
[2018HN省队集训D5T2] party 题意 给定一棵 \(n\) 个点以 \(1\) 为根的有根树, 每个点有一个 \([1,m]\) 的权值. 有 \(q\) 个查询, 每次给定一个大小为 ...
- [2018HN省队集训D5T1] 沼泽地marshland
[2018HN省队集训D5T1] 沼泽地marshland 题意 给定一张 \(n\times n\) 的棋盘, 对于位置 \((x,y)\), 若 \(x+y\) 为奇数则可能有一个正权值. 你可以 ...
随机推荐
- Java虚拟机JVM学习03 连接过程:验证、准备、解析
Java虚拟机JVM学习03 连接过程:验证.准备.解析 类被加载后,就进入连接阶段. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 连接阶段三个步骤:验证.准备和解析. 类 ...
- 【代码笔记】iOS-仿安卓,本页出现多个选择项
一,效果图. 二,代码. //点击任何处,弹出提示选项 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UIAlert ...
- UITableView与UISearchController搜索及上拉加载,下拉刷新
#import "ViewController.h" #import "TuanGouModel.h" #import "TuanGouTableVi ...
- 【Android】Mac安装EasyTether导致无法识别设备的问题
正文 想让手机走PC网络,然后抓包,于是搜索一番后安装了一个叫EasyTether的软件.还没来得及测试,就忙着写代码去了,重启MAC以后就发现连不上手机了,一开始并没有怀疑是 EasyTether的 ...
- django 验证用户是否登陆
第一步 指定一下登陆url. url(r'^accounts/login/$', include(xadmin.site.urls)), 由于我用的xadmin故而指向了xadmin,如果使用默认的a ...
- (视频) 基于HTML5的服务器远程访问工具
现在云计算这么发达,基本上每个人都多少有几台Windows或者Linux服务器运行在云端,要直接进入这些服务器进行配置就需要使用类似远程桌面或者Putty这类的工具,虽然大多数Windows电脑都自带 ...
- JAVA同步容器和并发容器
同步容器类 同步容器类的创建 在早期的JDK中,有两种现成的实现,Vector和Hashtable,可以直接new对象获取: 在JDK1.2中,引入了同步封装类,可以由Collections.sync ...
- Android中的单例模式
定义: 单例模式:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 使用场景: 确保某一个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一 ...
- SQL Server 2008 存储过程,带事务的存储过程(创建存储过程,删除存储过程,修改存储过
SQL Server 2008 存储过程,带事务的存储过程(创建存储过程,删除存储过程,修改存储过 存储过程 创建存储过程 use pubs --pubs为数据库 go create proc ...
- CentOS7安装图形界面和修改运行级别
CentOS7系统如果用mini镜像安装或者服务器版本安装,默认是没有安装图形界面的.如果需要额外去安装图形界面,可以手动来安装CentOS Gnome GUI包.然后会总结一下,在CentOS7系统 ...