【BZOJ】2730: [HNOI2012]矿场搭建

传送门 http://www.lydsy.com/JudgeOnline/problem.php?id=2730

思路可以参考Po姐姐博客
传送门 http://blog.csdn.net/popoqqq/article/details/40784625

我的代码是处理了独立点的情况,然而数据并不给力

#include<stdio.h>
#include<cstring>
#include<algorithm>
#define N 1005
#define V e[i].v
using namespace std;
  
struct edge{int v,n;}e[N<<1];
  
int tot,cnt,ans1,s[N],low[N],dep[N],stack[N],belong[N],top,n,m;
long long ans2;
  
inline void push(const int &u,const int &v){e[++tot]=(edge){v,s[u]};s[u]=tot;}
  
inline void prepare()
{
    memset(dep,0,sizeof(dep));
    memset(belong,0,sizeof(belong));
    memset(s,0,sizeof(s));
    n=cnt=ans1=tot=0;ans2=1;
}
  
void dfs(const int &u)
{
    dep[u]=low[u]=++cnt;
    for (int i=s[u];i;i=e[i].n) if (dep[V]) low[u]=min(low[u],dep[V]);
    else
    {
        dfs(V);
        low[u]=min(low[u],low[V]);
        if (dep[u]<=low[V]) belong[u]++;
    }
}
  
void solve(const int &u)
{
    dep[u]=low[u]=++cnt;
    stack[++top]=u;
    for (int i=s[u];i;i=e[i].n) if (dep[V]) low[u]=min(low[u],dep[V]);
    else
    {
        solve(V);
        low[u]=min(low[u],low[V]);
        if (dep[u]<=low[V])
        {
            int t,tmp=0,size=1;  
            do{  
                t=stack[top--];  
                if (1<belong[t]) ++tmp;  
                ++size;  
            }while(t!=V);
            if (1<belong[u]) ++tmp;
            if (!tmp) ans1+=2,ans2*=size*(size-1)>>1;
            if (tmp==1) ans1++,ans2*=size-1;
        }
    }
}
  
int main()
{
    for (int T=1;;T++)
    {
        scanf("%d",&m);
        if (m==0) return 0;
        prepare();
        for (int i=1,u,v;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            push(u,v);push(v,u);
            n=max(n,max(u,v));
        }
        for (int i=1;i<=n;i++) if (!dep[i]) dfs(i);
        else belong[i]++;
        memset(dep,0,sizeof(dep));cnt=0;
        for (int i=1;i<=n;i++) if (!dep[i]) solve(i);
        for (int i=1;i<=n;i++) if (!s[i]) ans1++;
        printf("Case %d: %d %lld\n",T,ans1,ans2);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值