BZOJ 2208: [Jsoi2010]连通数 tarjan bitset
2208: [Jsoi2010]连通数
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://www.lydsy.com/JudgeOnline/problem.php?id=2208
Description
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
3
010
001
100
Sample Output
9
HINT
对于100%的数据,N不超过2000。
题意
题解:
先缩点,变成一个有向无环图之后,再直接跑dp就好了
可以用bitset做
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <bitset> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200051 #define mod 10007 #define eps 1e-9 int Num; //const int inf=0x7fffffff; //нчоч╢С const int inf=0x3f3f3f3f; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //************************************************************************************** vector<int> Q[maxn]; char s[2010]; int dfn[2010],low[2010],_clock=0; int sta[2010],top; bool in_sta[2010]; int changed[2010],scc,num[2010]; bitset<2010> have[2010]; void tarjan(int x) { dfn[x]=low[x]=++_clock; sta[++top]=x; in_sta[x]=1; for(int i=0;i<Q[x].size();i++) { int v = Q[x][i]; if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]); else if(in_sta[v]) low[x]=min(low[x],dfn[v]); } if(dfn[x]==low[x]) { int temp; ++scc; do{ temp = sta[top--]; in_sta[temp]=0; changed[temp]=scc; ++num[scc]; }while(temp!=x); } } int main() { int n=read(); for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=n;j++) { if(s[j]=='1') Q[i].push_back(j); } } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++) have[changed[i]][i]=1; int ans=0; for(int i=1;i<=scc;i++) { ans+=num[i]*num[i]; bitset<2010>temp; for(int x = 1;x<=n;x++) { if(changed[x]==i) { for(int j=0;j<Q[x].size();j++) { int v = Q[x][j]; if(changed[v]!=i) temp|=have[changed[v]]; } } } ans+=num[i]*temp.count(); have[i]|=temp; } printf("%d\n",ans); }