• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
AC_Artist.zig_zag
然而我依然在补题、
博客园    首页    新随笔    联系   管理    订阅  订阅

bzoj 1093 最大半连通子图

这个题一定要把题意弄清楚,然后就是发现可以缩点搞,缩点了以后这个最大半连通子图就是一条最长的单向链。

然后用类似树型dp的方法(这里是BFS更新答案),可以把答案求出来。

注意缩点以后可能会有重边(参考proverbs大神的博客)如果用DFS更新dp的话,不好判断重边。

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 120000
  7 #define maxm 1200000
  8 #define inf 2147483646
  9 using namespace std;
 10 struct et
 11 {
 12     int s,t,next;
 13 }d[maxm],e[maxm];
 14 int f[maxn],g[maxn];
 15 int dfn[maxn],low[maxn],web[maxn],sum[maxn],q[maxn];
 16 int fir[maxn],last[maxn],v[maxn],id[maxn],stack[maxn],vis[maxn];
 17 int n,m,tot,tt,num,ms,tim,top;
 18 
 19 inline void insert(int x,int y)
 20 {
 21     e[++tot].s=x; e[tot].t=y; e[tot].next=fir[x]; fir[x]=tot;
 22 }
 23 inline void add(int x,int y)
 24 {
 25     d[++tt].s=x; d[tt].t=y; d[tt].next=last[x]; last[x]=tt;
 26 }
 27 
 28 inline void tarjan(int now)
 29 {
 30     dfn[now]=low[now]=++tim;
 31     stack[++top]=now;
 32     v[now]=1;
 33     for (int j=last[now];j;j=d[j].next)
 34     {
 35         int k=d[j].t;
 36         if (!v[k]) tarjan(k);
 37         if (v[k]<2) low[now]=min(low[now],low[k]);
 38     }
 39     if (dfn[now]==low[now])
 40     {
 41         num++;
 42         while (stack[top+1]!=now)
 43         {
 44             v[stack[top]]=2;
 45             web[stack[top]]=num;
 46             sum[num]++;
 47             --top;
 48         }
 49     }
 50 }
 51 
 52 inline void dfs(int now)
 53 {
 54     v[now]=1;
 55     for (int j=last[now];j;j=d[j].next)
 56     {
 57         int k=d[j].t;
 58         if (web[now]!=web[k]) insert(web[now],web[k]),++id[web[k]];
 59         if (!v[k]) dfs(k);
 60     }
 61 }
 62 
 63 inline void find()
 64 {
 65     memset(vis,0,sizeof(vis));
 66     int head=0,tail=0;
 67     for (int i=1;i<=num;i++) 
 68         if (!id[i]) q[++tail]=i,f[i]=sum[i],g[i]=1;
 69     while (head<tail)
 70     {
 71         int now=q[++head];
 72         for (int j=fir[now];j;j=e[j].next)
 73         {
 74             int k=e[j].t;
 75             if (!(--id[k])) q[++tail]=k;
 76             if (vis[k]==now) continue;
 77             if (f[now]+sum[k]>f[k]) f[k]=f[now]+sum[k],g[k]=g[now];
 78             else
 79             if (f[now]+sum[k]==f[k]) g[k]=(g[k]+g[now])%ms;
 80             vis[k]=now;
 81         }
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     //freopen("semi.in","r",stdin);
 88     scanf("%d %d %d",&n,&m,&ms);
 89     int x,y;
 90     for (int i=1;i<=m;i++)
 91         scanf("%d %d",&x,&y),add(x,y);
 92     for (int i=1;i<=n;i++)
 93         if (!v[i]) tarjan(i);
 94     memset(v,0,sizeof(v));
 95     for (int i=1;i<=n;i++) 
 96         if (!v[i]) dfs(i);
 97     find();
 98     int ans=0,fig=0;
 99     for (int i=1;i<=num;i++)
100     {
101         if (f[i]>ans) ans=f[i],fig=g[i];
102         else
103         if (f[i]==ans) fig=(fig+g[i])%ms;
104     }
105     printf("%d\n",ans);
106     printf("%d\n",fig);
107     return 0;
108 }

 

AC without art, no better than WA !
posted @ 2013-03-26 18:33  Zig_zag  阅读(350)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3