usaco 4.3 Street Race

 求有向图割点和分裂点,由于数据很小,直接枚举,去掉某点,然后判断即可,需要注意的地方是分裂点一定是割点

 

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <map>
  4. #include <vector>
  5. using namespace std;
  6. /*
  7. PROG: race3
  8. LANG: C++
  9. ID: heben991
  10. */
  11. const int N = 110;
  12. int n, m, low[N],num[N], g[N][N];
  13. bool cut[N], split[N];
  14. int mark[N];
  15. void dfs_cut(int x)
  16. {
  17.     int i, j, k, t;
  18.     mark[x]=1;
  19.     for(i = 0; i <= n; ++i)
  20.     if(g[x][i] && !mark[i])
  21.     {
  22.         dfs_cut(i);
  23.     }
  24. }
  25. void dfs1(int x)
  26. {
  27.     int i;
  28.     mark[x]=1;
  29.     for(i = 0; i <= n; ++i)
  30.     if(!mark[i] && g[x][i])
  31.     {
  32.         dfs1(i);
  33.     }
  34. }
  35. bool dfs2(int x)
  36. {
  37.     int i;
  38.     bool ret=1;
  39.     mark[x]=2;
  40.     for(i = 0; i <= n; ++i)
  41.     if(g[x][i] && mark[i]!=2)
  42.     {
  43.         if(mark[i]==1)return 0;
  44.         ret = ret && dfs2(i);
  45.     }
  46.     return ret;
  47. }
  48. bool get_split(int x)
  49. {
  50.     int i, j, k, t;
  51.     memset(mark,0,sizeof(mark));
  52.     mark[x]=1; // key step
  53.     dfs1(0);
  54.     mark[x]=0;
  55.     return dfs2(x);
  56. }
  57. int main()
  58. {
  59.     int i, j, k, t, x, y;
  60.     freopen("race3.in""r", stdin);
  61.     freopen("race3.out","w",stdout);
  62.     while( scanf("%d", &x)==1 && x!=-1)
  63.     {
  64.         while(x!=-2)
  65.         {
  66.             if(x!=n)g[n][x] = 1;
  67.             scanf("%d", &x);
  68.         }
  69.         ++n;
  70.     }
  71.     --n;
  72.     int count=0;
  73.     for(i = 1; i < n; ++i)
  74.     {
  75.         memset(mark,0,sizeof(mark));
  76.         mark[i] = 1;
  77.         dfs_cut(0);
  78.         if(!mark[n]) cut[i] = 1, ++count;
  79.     }
  80.     printf("%d",count);
  81.     count = 0;
  82.     for(i = 1; i < n; ++i)
  83.     if(cut[i])
  84.     {
  85.         printf(" %d", i);
  86.         split[i] = get_split(i);
  87.         if(split[i]) count++;
  88.     }
  89.     puts("");
  90.     printf("%d", count);
  91.     for(i = 1; i < n; ++i)
  92.     if(split[i])printf(" %d",i);
  93.     puts("");
  94.     return 0;
  95. }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值