BZOJ_3935_Rbtree
https://lydsy.com/JudgeOnline/problem.php?id=3935
分析:
- 如果知道更改后的状态,那么代价和是否合法都能求出来
- 对不合法的情况也设一个估价函数。
- 随机这个01串,模拟退火即可。
(已更新正解)
代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
#define N 550
typedef long long ll;
#define inf 0x3f3f3f3f
typedef double f2;
f2 Rand() {
return f2(rand())/RAND_MAX;
}
int head[N],to[N<<1],nxt[N<<1],n,cnt,w[N],X,val[N<<1];
ll dis[N][N];
int len[N],vec[N][N];
inline void add(int u,int v,int w) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
}
void dfs(int x,int y,int rt) {
int i;
for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
dis[rt][to[i]]=dis[rt][x]+val[i];
dfs(to[i],x,rt);
}
}
struct A {
int a[N],ans;
A() {ans=inf;}
}ANS,TMP;
int check(const A &x) {
int i,j,re=0;
for(i=1;i<=n;i++) if(x.a[i]==0) {
int flg=0;
for(j=1;j<=len[i];j++) if(x.a[vec[i][j]]) {
flg=1; break;
}
if(!flg) re++;
}
return re;
}
void calc(A &x) {
int i,t=0;
for(i=1;i<=n;i++) t+=(x.a[i]!=w[i]);
int tmp=check(x);
if(tmp) x.ans=tmp*2+(n>>1);
else x.ans=(t>>1);
if(x.ans<ANS.ans) ANS=x;
}
int t0[N],t1[N],l1,l0;
A kuo(const A &x,int y) {
A re=x;
int i;
for(i=1;i<=y;i++) {
int l=rand()%l1+1,r=rand()%l0+1;
swap(re.a[t1[l]],re.a[t0[r]]);
}
return re;
}
void orztuihuo(f2 BG,f2 ED,f2 d) {
calc(TMP);
A now=TMP;
l0=l1=0;
int i;
for(i=1;i<=n;i++) {
if(!now.a[i]) t0[++l0]=i;
else t1[++l1]=i;
}
for(;BG>ED;BG*=d) {
A nxt=kuo(now,max(1.0,BG));
calc(nxt);
if(nxt.ans < now.ans || Rand() < exp((now.ans-nxt.ans)/BG)) {
now=nxt;
l0=l1=0;
for(i=1;i<=n;i++) {
if(!now.a[i]) t0[++l0]=i;
else t1[++l1]=i;
}
}
}
for(i=1;i<=10000;i++) {
A nxt=kuo(ANS,1);
calc(nxt);
}
}
int main() {
srand(114514); rand();
scanf("%d%d",&n,&X);
int i,j;
for(i=1;i<=n;i++) scanf("%d",&w[i]);
int x,y,z;
for(i=1;i<n;i++) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
for(i=1;i<=n;i++) dfs(i,0,i);
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j&&dis[i][j]<=X) {
vec[i][++len[i]]=j;
}
ANS.ans=inf;
int sw=0;
for(i=1;i<=n;i++) TMP.a[i]=w[i],sw+=w[i];
random_shuffle(TMP.a+1,TMP.a+n+1);
if(n<=100) orztuihuo(50,0.001,0.999);
else if(sw>100) orztuihuo(100,0.1,0.999998);
else orztuihuo(100,0.01,0.99993);
// for(i=1;i<=n;i++) printf("%d ",ANS.a[i]); puts("");
printf("%d\n",ANS.ans>n?-1:ANS.ans);
}
正解:
我的做法是设\(i\)节点\(x_i\)表示是否被交换过。
那么如果原来是\(0\),现在就是\(x_i\),原来是1,现在就是\(1-x_i\)。
列出几个限制然后单纯形法水过
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
typedef double f2;
#define N 515
#define eps 1e-8
int head[N],to[N<<1],nxt[N<<1],val[N<<1],n,cnt,wa[N];
ll dis[N][N],X;
f2 a[N<<1][N];
inline void add(int u,int v,int w) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
}
void dfs(int x,int y,int rt,ll d) {
dis[rt][x]=d;
int i;
for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
dfs(to[i],x,rt,d+val[i]);
}
}
void pivot(int r,int c,int n,int m) {
int i,j;
f2 t=-a[r][c]; a[r][c]=-1;
for(i=0;i<=n;i++) a[r][i]/=t;
for(i=0;i<=m;i++) if(abs(a[i][c])>eps&&i!=r) {
t=a[i][c]; a[i][c]=0;
for(j=0;j<=n;j++) a[i][j]+=t*a[r][j];
}
}
void simplex(int n,int m) {
int i,j,k;
f2 t;
while(1) {
i=j=0;
t=-eps;
for(k=1;k<=m;k++) if(a[k][0]<t) t=a[i=k][0];
if(!i) break;
for(k=1;k<=n;k++) if(a[i][k]>eps) {
j=k; break;
}
if(!j) {puts("-1"); return ;}
pivot(i,j,n,m);
}
while(1) {
i=j=0;
t=eps;
for(k=1;k<=n;k++) if(a[0][k]>t) t=a[0][j=k];
if(!j) break;
t=1e9;
for(k=1;k<=m;k++) if(a[k][j]<-eps&&(-a[k][0]/a[k][j])<t) {
t=-a[k][0]/a[k][j]; i=k;
}
if(!i) {puts("INF"); return ;}
pivot(i,j,n,m);
}
if(abs(a[0][0])<eps) puts("0");
else if(-a[0][0]>n) puts("-1");
else printf("%.0f\n",-a[0][0]/2);
}
int main() {
scanf("%d%lld",&n,&X);
int i,x,y,z,j,sum=0;
for(i=1;i<=n;i++) scanf("%d",&wa[i]),sum+=wa[i];
for(i=1;i<n;i++) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
for(i=1;i<=n;i++) {
dfs(i,0,i,0);
}
for(i=1;i<=n;i++) a[0][i]=-1;
for(i=1;i<=n;i++) {
int t=0;
for(j=1;j<=n;j++) {
if(dis[i][j]<=X) {
if(wa[j]) t++,a[i][j]=-1;
else a[i][j]=1;
}
}
a[i][0]=t-1;
}
int t=0;
for(i=1;i<=n;i++) {
if(wa[i]) t++,a[n+1][i]=-1;
else a[n+1][i]=1;
}
a[n+1][0]=t-sum;
t=0;
for(i=1;i<=n;i++) {
if(wa[i]) t--,a[n+2][i]=1;
else a[n+2][i]=-1;
}
a[n+2][0]=t+sum;
int tot=n+2;
for(i=1;i<=n;i++) {
a[++tot][i]=-1;
a[tot][0]=1;
}
simplex(n,tot);
}
BZOJ_3935_Rbtree的更多相关文章
随机推荐
- oracle学习之路(四) ---------PL/SQL 表,二维数组(TABLE)
LOB类型 ORACLE提供了LOB (Large OBject)类型.用于存储大的数据对象的类型.ORACLE眼下主要支持BFILE, BLOB, CLOB 及 NCLOB 类型. NCLOB 存储 ...
- sprint3 【每日scrum】 TD助手站立会议第五天
站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 通过网上的介绍懂得了闹钟的添加和工作原理,然后加入了震动效果 在添加日程类型处添加了选择闹钟间隔多长时间相应,并写了闹钟运行的类 广播协议也弄 ...
- Redis学习手册(List数据类型)(转)
一.概述: 在Redis中,List类型是按照插入顺序排序的字符串链表.和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的 元素.在插入时,如果该键并不存在,Redi ...
- Lua学习九----------Lua字符串
© 版权声明:本文为博主原创文章,转载请注明出处 1.Lua字符串 - ''单引号间的一串字符 - ""双引号之间的一串字符 - [[]]之间的一串字符 2.Lua转义字符 3.字 ...
- python学习(一)运行第一个python脚本
当然这里指的是在linux或者unix下,像写bash脚本那样 #!/usr/bin/python print('The Bright Side ' + 'of Life...') 反正我建议就算一开 ...
- CentOS下安装python3.x版本
现在python都到了3.x版本,但是centos中自带的python仍然是2.7版本的,所以想把python换成3.x版本的. 但是这个地方有个坑,你要是直接编译安装了python3.x之后,估计你 ...
- JQuery如何获取按键的unicode编码?
$("selector").keyup(function(xxx){ var myEvent = xxx; var code = myEvent.keyCode; alert(co ...
- zeroMQ研究(转)
偶尔一个机会,了解了下zeroMQ消息队列. 1 ZeroMQ概述 ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型.连接处理.帧.甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接 ...
- android 用webView作为编辑器 各种问题
1.首先我要说明一下为什么要写这个博客,因为公司最近需要一个自定义的编辑器,苦于没有思路在网上找了好久,看到了好多android实现的编辑器(其实也就那么几个并不多),公司需求和网页端同步共享创建的文 ...
- Android OkHttp的Cookie自己主动化管理
Android中在使用OkHttp这个库的时候.有时候须要持久化Cookie,那么怎么实现呢.OkHttp的内部源代码过于复杂,不进行深究.这里仅仅看当中的HttpEngineer里面的部分源代码,在 ...