首页 > Web开发 > 详细

【tarjan+缩点】POJ1236[IOI1996]-Network of Schools

时间:2016-02-19 23:11:38      阅读:517      评论:0      收藏:0      [点我收藏+]

【题意】

见:http://blog.csdn.net/ascii991/article/details/7466278

【思路】

缩点+tarjan,思路也可以到上面的博客去看。(吐槽:这道题其实我没有AC。我过了当年IOI的数据,而把别人AC掉的程序带进去,明显过不了IOI的数据!求POJ修正一下!)

【错误点】

1.tarjan要进行多次,详见程序注释

2.循环从0开始还是从1开始要看清楚!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<vector>
  6 #include<stack>
  7 using namespace std;
  8 const int MAXN=100+5;
  9 int n;//学校的总数 
 10 int u[MAXN],v[MAXN];//记录每一条边的起始点和终点
 11 int sp[MAXN];//记录缩点之后每个点对应的编号
 12 int tot=0;//有向图中边的总数 
 13 int vis[MAXN]; 
 14 int instack[MAXN];
 15 int dfn[MAXN],low[MAXN];
 16 int indegree[MAXN],outdegree[MAXN];//记录缩点后的每一个点的入度与出度 
 17 vector<int> E[MAXN]; 
 18 stack<int> S;
 19 int T=0;
 20 int cnt=0;//为缩点后的每一个点编号 
 21 
 22 void tarjan(int u)
 23 {
 24     dfn[u]=low[u]=++T;
 25     vis[u]=1;
 26     S.push(u);
 27     instack[u]=1;
 28     
 29     for (int i=0;i<E[u].size();i++)
 30     {
 31         int son=E[u][i];
 32         if (!vis[son])
 33         {
 34             tarjan(son);
 35             low[u]=min(low[son],low[u]);
 36         }
 37         else
 38         if (vis[son] && instack[son])
 39             low[u]=min(dfn[son],low[u]);
 40     }
 41     
 42     if (dfn[u]==low[u])
 43     {
 44         cnt++;
 45         int x;
 46         do
 47         {
 48              x=S.top();
 49              S.pop();
 50              sp[x]=cnt;
 51              instack[x]=0;
 52         }while (x!=u);
 53     }
 54 } 
 55 
 56 void init()
 57 {
 58     memset(vis,0,sizeof(vis));
 59     memset(instack,0,sizeof(instack));
 60     scanf("%d",&n);
 61     for (int i=1;i<=n;i++)
 62     {
 63         int to;
 64         while (scanf("%d",&to) && to)
 65         {
 66             tot++;
 67             u[tot]=i;v[tot]=to;
 68             E[i].push_back(to);
 69         }
 70     }
 71 }
 72 
 73 void find()
 74 {
 75     memset(indegree,0,sizeof(indegree));
 76     memset(outdegree,0,sizeof(outdegree));
 77     if (cnt>1)
 78     {
 79         for (int i=1;i<=tot;i++)
 80         /*错误点:写成了i=0;i<tot,导致有时候没有进入循环!*/
 81         {
 82             if (sp[u[i]]!=sp[v[i]])
 83             {
 84                 outdegree[sp[u[i]]]++;
 85                 indegree[sp[v[i]]]++;
 86             }//找出缩点后各点的出度和入度 
 87         }
 88         
 89         int noin=0,noout=0;
 90         for (int i=1;i<=cnt;i++)
 91         {
 92             if (indegree[i]==0) noin++;
 93             if (outdegree[i]==0) noout++;
 94         }
 95         cout<<noin<<endl;
 96         cout<<max(noin,noout)<<endl;
 97     }
 98     else if (cnt==1) printf("1\n\0\n");
 99 }
100 
101 int main()
102 {
103     init();
104     for (int i=1;i<=n;i++) if (vis[i]==0) tarjan(i);
105     /*错误点:一开始直接tarjan(1)了,导致有一些学校没有被访问到!每次随机从没有访问的某个结点开始!*/ 
106     find();
107     return 0;
108 }

 

【tarjan+缩点】POJ1236[IOI1996]-Network of Schools

原文:http://www.cnblogs.com/iiyiyi/p/5202432.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!