BZOJ4643 : 卡常大水题

将边按权值$A$从小到大排序,从小到大枚举$\max(A)$,然后双指针从大到小枚举$\max(B)$。

按权值$B$用大根堆维护所有已经加入的边,每次$\max(B)$减少时,不断取出权值$B$最大的边看看是否需要删除即可。

那么只需要检验这个图是否只有一个强连通分量。

考虑使用Kosaraju算法,维护一个未走过的点的集合,每次与出边表取交之后递归搜索可行后继点。

这显然可以用bitset来并行计算,时间复杂度单次$O(\frac{n^2}{32})$。

总时间复杂度$O(\frac{n^4}{32}+n^2\log n)$。

#include<cstdio>
#include<algorithm>
#include<queue>
#define N 155
using namespace std;
typedef unsigned int U;
typedef pair<int,int>P;
typedef pair<int,P>PI;
int n,i,j,k,m,b[N][N],eb[N*N],q[N],t,ans=~0U>>1;priority_queue<PI>Q;
struct E{int x,y,w;E(){}E(int _x,int _y,int _w){x=_x,y=_y,w=_w;}}ea[N*N];
inline bool cmp(const E&a,const E&b){return a.w<b.w;}
struct BIT{
  U v[5];
  void flip(int x){v[x>>5]^=1U<<(x&31);}
  int get(int x){return v[x>>5]>>(x&31)&1;}
}g0[N],g1[N],v;
inline void addedge(int x,int y){
  if(x==y||b[x][y]>eb[j])return;
  Q.push(PI(b[x][y],P(x,y)));
  g0[x].flip(y);
  g1[y].flip(x);
}
inline void deledge(int x,int y){
  g0[x].flip(y);
  g1[y].flip(x);
}
void dfs1(int x){
  v.flip(x);
  for(int i=0;i<5;i++)while(1){
    U o=v.v[i]&g0[x].v[i];
    if(!o)break;
    dfs1(i<<5|__builtin_ctz(o));
  }
  q[++t]=x;
}
void dfs2(int x){
  v.flip(x);
  for(int i=0;i<5;i++)while(1){
    U o=v.v[i]&g1[x].v[i];
    if(!o)break;
    dfs2(i<<5|__builtin_ctz(o));
  }
}
inline bool check(){
  int i;
  for(i=0;i<5;i++)v.v[i]=0;
  for(i=0;i<n;i++)v.flip(i);
  for(t=i=0;i<n;i++)if(v.get(i))dfs1(i);
  for(i=0;i<n;i++)v.flip(i);
  dfs2(q[t]);
  for(i=0;i<5;i++)if(v.v[i])return 0;
  return 1;
}
void solve(){
  sort(ea+1,ea+m+1,cmp);
  sort(eb+1,eb+m+1);
  for(i=1,j=m;i<=m;i++){
    addedge(ea[i].x,ea[i].y);
    while(check()){
      ans=min(ans,ea[i].w+eb[j]);
      if(!(--j))return;
      while(!Q.empty()){
        PI t=Q.top();
        if(t.first<=eb[j])break;
        Q.pop();
        deledge(t.second.first,t.second.second);
      }
    }
  }
}
int main(){
  scanf("%d",&n);
  for(m=i=0;i<n;i++)for(j=0;j<n;j++)scanf("%d",&k),ea[++m]=E(i,j,k);
  for(m=i=0;i<n;i++)for(j=0;j<n;j++)scanf("%d",&b[i][j]),eb[++m]=b[i][j];
  solve();
  return printf("%d",ans),0;
}

  

时间: 2024-10-17 04:17:57

BZOJ4643 : 卡常大水题的相关文章

[CSP-S模拟测试]:卡常题/b(基环树+DP)

题目描述 $ρ$有一个二分连通无向图,$X$方点.$Y$方点均为$n$个(编号为$1\sim n$).这个二分图比较特殊,每一个$Y$方点的度为$2$,一条黑色边,一条白色边.所有黑色边权值均为$a$,所有白色边权值均为$b$.选择一个$X$方点,代价为连接的所有边的权值之和.激活一个$Y$方点,需要选择至少一个与之相邻的$X$方点.现在,$ρ$想激活每个$Y$方点,他想知道最小的总代价.不过$ρ$很善良,他给你开了$O2$优化.这样你就不会被卡常了.当然,除非你真的连读入优化都不想写,或者常数

第三届山西省赛1004 一道大水题(scanf)

一道大水题 时间限制: C/C++ 2000ms; Java 4000ms 内存限制: 65535KB 通过次数: 44 总提交次数: 1020 问题描述 Dr. Pan作为上兰帝国ACM的总负责人,对队员的队员的训练也是日常关心,他要求每周要有一位队员出一道题目.不知过了多少年,终于轮到Shiyiliang出题了,他费尽脑汁,终于出了一道大水题 给定一个偶数n,n的取值范围为[-1e18,1e18],要求一对整数x,y满足以下条件: 1.x*y==n 2.x与n必须同号,即如果n>0则x>0

Codeforces 988D Points and Powers of Two 【性质】【卡常】

这道题关键在于想到两个性质,想到就好做了.这还是我做过的第一道卡常题 1.满足题目中条件的子集,其中元素个数不能大于3 2.如果最大子集为3的话,那一定是x-2^i,  k, x+2^i的形式,我们枚举x就好了,然后i的次数是log10^9:如果最大子集是2,那就是x,x+2^i的形式,同样枚举x:如果最大子集是1,输出a[1]就行 整体复杂度是O(n*logn*log10^9) 1 #include<iostream> 2 #include<set> 3 using namesp

论OI中各种玄学卡常

当你在写程序的时候一般出现过这种无比悲剧的情况: 你讨厌卡常?下面有二则小故事: 作为一个经常出题的人,其实很多时候出题时的画风是这样的:"我有一个绝妙的\(O(nlog^2n)\)的算法,我来出道题吧""咦怎么只能跑 \(5w\) 啊,好咸鱼啊,我要让它能跑 \(10w\),嗯现在 \(10w\) 只要 \(0.3s\) 了,要不努把力跑个 \(20w\) 吧"然后就没有然后了.. 开O2之后FFT会比不开快几倍? 不开\(O2\):\(NTT\)比\(FFT\)

PAT甲题题解-1101. Quick Sort (25)-大水题

快速排序有一个特点,就是在排序过程中,我们会从序列找一个pivot,它前面的都小于它,它后面的都大于它.题目给你n个数的序列,让你找出适合这个序列的pivot有多少个并且输出来. 大水题,正循环和倒着循环一次,统计出代码中的minnum和maxnum即可,注意最后一定要输出'\n',不然第三个测试会显示PE,格式错误. #include <iostream> #include <cstdio> #include <algorithm> #include <map&

大水题(water)

题目描述dzy 定义一个 $n^2$ 位的数的生成矩阵 $A$ 为一个大小为 $n \times n$ 且 Aij 为这个数的第 $i \times n+j-n$ 位的矩阵.现在 dzy 有一个数 $n^2$ 位的数 k,他想知道所有小于等于 k 的数的 $n \times n$ 生成矩阵有多少种.(如果不足 $n^2$ 位则补前缀零)输入输出格式输入格式第一行一个数 $n$,第二行一个 $n^2$ 位的数 $k$输出格式仅一行表示答案,答案可能很大,你只需输出答案对 $10^9 + 7$ 取模

[补档]两个奇怪的大水题

导引 这是两道由OSU(貌似是一个我没有听说过的游戏)引申出的大水题(淼到不行啊喂),壹佰万行代码哦. T1 OSU! 题目 osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串.在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释) 现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五

Pythagorean Triples CodeForces - 707C 推理题,大水题

给定一个数n(1 <= n <= 1e9),判断这个数是否是一个直角三角形的边长,如果是,则输出另外两条边(1 <= x <= 1e18),否则输出-1. 参考题解:http://blog.csdn.net/harlow_cheng/article/details/69055614 首先,当n <= 2 的时候无解,其他时候都有解 假设n是直角边,a是斜边,则n^2 + b^2 = a^2; n^2 = (a + b)*(a - b); ①假设n是偶数,则另(a - b) =

UVA12709 Falling Ants(超级大水题)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4447 Ps:此题超级水,但是光看题目就会被吓一跳.确实题目很长,不过有用的语句少之又少,介绍一大堆与AC没有半毛钱关系的东西,汗颜. 此题告诉我们题目长不一定是最难得题,反而有时候是最简单的题,就看你有