JSOI2010 联通数
这道题的题目描述看起来很奇怪。实际上的意思是要求在这个有向图之内能到达的点对有多少,解释一下题里的图片就是(1,1),(1,2),(1,3),(1,4),(1,5),(2,2),(2,3),(2,4),(2,5),(3,3),(3,4),(3,5),(4,4),(5,5)一共14个。
先小声说一下这题固输n^2可以得到90pts……
然后我们首先考虑非常暴力的做法,就是先手tarjan缩点,存每个联通块里面的节点个数,在新图上直接进行dfs,把每个点所能到达的点搜出来就行。
我也不知道能跑多快……但是如上文所述你固输都有90所以数据比较水,我一共跑了50ms就过了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#include<bitset>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int N = ;
const double eps = 1e-;
const double fi = 0.61803399;
const double fim = 0.38196601; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} struct edge
{
int next,to,from;
}e[N<<],e1[N<<];
int n,g[M][M],dfn[M],low[M],stack[M],top,idx,cur,ecnt,head[M],sd[M],h[M],sz[M],ecnt1,q[M],curr,tot;
char s[M];
ll ans;
bool vis[M],pd[M]; void add(int x,int y)
{
e[++ecnt].to = y;
e[ecnt].from = x;
e[ecnt].next = head[x];
head[x] = ecnt;
} void tarjan(int x)
{
low[x] = dfn[x] = ++idx;
vis[x] = ,stack[++top] = x;
for(int i = head[x];i;i = e[i].next)
{
if(!dfn[e[i].to]) tarjan(e[i].to),low[x] = min(low[x],low[e[i].to]);
else if(vis[e[i].to]) low[x] = min(low[x],low[e[i].to]);
}
if(low[x] == dfn[x])
{
int p;
cur++;
while(p = stack[top--])
{
sd[p] = cur,vis[x] = ,sz[cur]++;
if(x == p) break;
}
}
} void dfs(int x)
{ tot += sz[x],pd[x] = ,q[++curr] = x;
for(int i = h[x];i;i = e1[i].next)
{
if(pd[e1[i].to]) continue;
dfs(e1[i].to);
}
} int main()
{
n = read();
rep(i,,n)
{
scanf("%s",s);
rep(j,,n-) if(s[j] == '') add(i,j+);
}
rep(i,,n) if(!dfn[i]) tarjan(i);
rep(i,,ecnt)
{
int r1 = sd[e[i].from],r2 = sd[e[i].to];
if(r1 != r2)
{
e1[++ecnt1].to = r2;
e1[ecnt1].next = h[r1];
e1[ecnt1].from = r1;
h[r1] = ecnt1;
}
}
rep(i,,cur)
{
rep(i,,curr) q[i] = ;tot = ;
dfs(i);
rep(i,,curr) pd[q[i]] = ;
ans += tot * sz[i];
}
printf("%lld\n",ans);
return ;
}
这样很神奇你的搜索就过了……
之后我们再说一种别的做法,他有一个高大上的名字,叫Floyd传递闭包!
这个东西可以判断有向图两点之间是否连通,一开始它的形状和初始给定的邻接矩阵是一样的,不过大对角线上的点都变成了1.
正常的dp是三重循环枚举,dp[i][j] = dp[i][k] & dp[k][j]。不过这样枚举O(n^3)会T,然后我们发现只有能和不能到两种状态,所以我们引入一种强大的东西——bitset来帮我们优化。
使用bitset压缩一行的状态,这样的话转移方程就变成了dp[i] |= dp[j].这样我们只需要O(n^3/32)的复杂度,就可以过了。
看一下代码(炒鸡短)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#include<bitset>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const double eps = 1e-;
const double fi = 0.61803399;
const double fim = 0.38196601; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} bitset <> f[M];
int n;
char s[M];
ll ans; int main()
{
n = read();
rep(i,,n)
{
scanf("%s",s);
rep(j,,n-) if(s[j] == '') f[i][j+] = ;
f[i][i] = ;
}
rep(i,,n)
rep(j,,n) if(f[j][i]) f[j] |= f[i];
rep(i,,n) ans += f[i].count();
printf("%lld\n",ans);
return ;
}
JSOI2010 联通数的更多相关文章
- bzoj 3043: IncDec Sequence 模拟
3043: IncDec Sequence Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 248 Solved: 139[Submit][Statu ...
- ACM数学
1.burnside定理,polya计数法 这个专题我单独写了个小结,大家可以简单参考一下:polya 计数法,burnside定理小结 2.置换,置换的运算 置换的概念还是比较好理解的,< ...
- 【BZOJ 1483】[HNOI2009]梦幻布丁
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 链表,启发式合并. 把x变成y,和y全都变成x. 不论是前者还是后者.连续段的个数都是相同的,不影响结果. 那么我们把x,y中出现次 ...
- Codeforces Round #383 (Div. 2) C. Arpa's loud Owf and Mehrdad's evil plan(dfs+数学思想)
题目链接:http://codeforces.com/contest/742/problem/C 题意:题目比较难理解,起码我是理解了好久,就是给你n个位置每个位置标着一个数表示这个位置下一步能到哪个 ...
- CSPS模拟 77
%%两位AK爷zkt和skyh T1 位间独立,分别讨论 T2 维护标记,代替移位 T3 同一点对,多种联通,没法搞. 发现最多四路连通,考虑容斥. 显然的奇加偶减. 发现统计某种颜色的点之间的联通数 ...
- LCT 总结
刚开始学lct花了一晚上研究模板,调出来就感觉不怎么难打了. 对板子的浅显理解: lct维护树形联通块,通过splay维护实链,可以把需要的路径变换到一颗splay上维护. splay中的关系只依赖实 ...
- region特征
一: 查看阈值之后的region特征,可以通过特征检测来看,在工具栏上 region特征分三部分: 1.基础特征: region面积,中心,宽高,左上角及右下角坐标,长半轴短半轴椭圆方向,洞数及其面积 ...
- 第一阶段集训(这篇先写写tarjan以及圆方树)
第一阶段的集训结束了w,不得不说oi太长时间不整是会退步的. 怎么说好呢,集训这几天过的很充实,知识收货很多,题调的也不少,自己的目标更明确了吧,不过这几天集训也是可以看出蒟蒻就是蒟蒻,还是太菜了.. ...
- 【强联通分量缩点】【搜索】bzoj2208 [Jsoi2010]连通数
两次dfs缩点,然后n次dfs暴搜. #include<cstdio> #include<vector> #include<cstring> using names ...
随机推荐
- 安卓巴士Android开发神贴整理
10个经典的Android开源应用项目 http://www.apkbus.com/android-13519-1-1.html 安卓巴士总结了近百个Android优秀开源项目,覆盖Android开发 ...
- VS Code 列编辑功能说明
新版本v1.13.1或者附近的版本中的列编辑功能已经调整. 一.多光标插入功能 Alt+鼠标左键,添加多光标输入 二.自由多行选择 Alt键+鼠标左键拖动选择各行的部分内容 三.列选择 Shift+A ...
- BitmapFactory.Options对图片进行缩放
package com.pingyijinren.helloworld.activity; import android.graphics.Bitmap; import android.graphic ...
- HDU 6333 莫队+组合数
Problem B. Harvest of Apples Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K ...
- HDU 5700 区间交
枚举起点 二分终点 树状数组check #include<iostream> #include<cstring> #include<cmath> #include& ...
- Palindrome Partitioning (回文子串题)
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
- Topcoder 658Div2
补题风向标——>> 假装题意知道 A:暴力合成一遍了 n=s.size(); m=t.size(); ss+=s; tt+=t; if (ss==tt) or not; B:题意是给定 1 ...
- [Bzoj1015][JSOI2008]星球大战starwar(并查集)(离线处理)
1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 6849 Solved: 3204[Submit ...
- 51nod 马拉松30 C(构二分图+状压dp)
题意 分析 考虑一个图能被若干简单环覆盖,那么一定是每个点恰好一个出度,恰好一个出度 于是类似最小路径覆盖的处理,我们可以把每个点拆成2个点i和i',如果有一条边(i,j),那么将i和j'连起来 那么 ...
- Atom安装Markdown编辑器
1.安装插件 2.打开/关闭实时渲染: [Ctrl]+[Shift]+[M] 3.[增强]安装同步滚动插件(markdown-scroll-sync) 4.[增强]安装代码增强插件(language- ...