又是抄白书上的代码
不过发现了一个问题,当只有一个双连通分量的时候,如果算方法数的时候n前面不转换成64位就会出错。
代码:
</pre><pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=50005;
int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;
vector<int> G[maxn],bcc[maxn];
struct Edge
{
int u,v;
Edge(int u,int v):u(u),v(v){}
};
stack<Edge> S;
int dfs(int u,int fa)
{
int lowu=pre[u]=++dfs_clock;
int child=0;
for(int i=0;i<G[u].size();++i)
{
int v=G[u][i];
Edge e=(Edge){u,v};
if(!pre[v])
{
S.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=1;
bcc_cnt++;bcc[bcc_cnt].clear();
for(;;)
{
Edge x=S.top();S.pop();
if(bccno[x.u]!=bcc_cnt){bcc[bcc_cnt].push_back(x.u);bccno[x.u]=bcc_cnt;}
if(bccno[x.v]!=bcc_cnt){bcc[bcc_cnt].push_back(x.v);bccno[x.v]=bcc_cnt;}
if(x.u==u&&x.v==v)break;
}
}
}
else if(pre[v]<pre[u]&&v!=fa){
S.push(e);
lowu=min(lowu,pre[v]);
}
}
if(fa<0&&child==1)iscut[u]=0;
return lowu;
}
void find_bcc(int n)
{
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
memset(bccno,0,sizeof(bccno));
dfs_clock=bcc_cnt=0;
for(int i=0;i<n;++i)
{
if(!pre[i])dfs(i,-1);
}
}
int main()
{
// freopen("data.txt","r",stdin);
int m;
int kase=0;
while(scanf("%d",&m)&&m)
{
for(int i=0;i<m+6;++i)G[i].clear();
int n=0;
for(int i=0;i<m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
u--;v--;
n=max(n,u);
n=max(n,v);
G[u].push_back(v);
G[v].push_back(u);
}
n++;
find_bcc(n);
int num=0;
ll dif=1;
if(bcc_cnt==1)
{
num=2;
dif=(ll)n*(n-1)/2;//白书上面这里没有加上强制类型转换,如果不加过不去
}
else
for(int i=1;i<=bcc_cnt;++i)
{
int c=0;
for(int j=0;j<bcc[i].size();++j)if(iscut[bcc[i][j]])c++;
if(c<2)
{
// cout<<i<<endl;
num++;
dif*=(ll)(bcc[i].size()-1);
}
}
printf("Case %d: ",++kase);
printf("%d %lld\n",num,dif);
}
return 0;
}