poj 1523"SPF"(无向图求割点)

传送门

 

题意:

  有一张联通网络,求出所有的割点;

  对于割点 u ,求将 u 删去后,此图有多少个联通子网络;

  对于含有割点的,按升序输出;

题解:

  DFS求割点入门题,不会的戳这里?求无向连通图的割点

AC代码: 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio> 
  4 using namespace std;
  5 #define mem(a,b) memset(a,b,sizeof(a))
  6 const int maxn=1e3+50;
  7 
  8 int num;
  9 int fa[maxn];
 10 int dfn[maxn];
 11 int low[maxn];
 12 bool vis[maxn];
 13 bool son[maxn];
 14 int artPoint[maxn];
 15 int head[maxn];
 16 struct Edge
 17 {
 18     int to;
 19     int next;
 20 }G[1000010];
 21 void addEdge(int u,int v)
 22 {
 23     G[num].to=v;
 24     G[num].next=head[u];
 25     head[u]=num++;
 26 }
 27 void DFS(int u,int f,int &k)
 28 {
 29     if(f == 1 && !son[u])
 30         artPoint[1]++;//求根节点的子树分支个数 
 31         
 32     fa[u]=f;
 33     vis[u]=true;
 34     dfn[u]=low[u]=++k;
 35     for(int i=head[u];~i;i=G[i].next)
 36     {
 37         int v=G[i].to;
 38         if(!vis[v])
 39         {
 40             DFS(v,u,k);
 41             
 42             if(u != 1 && low[v] >= dfn[u])
 43                 artPoint[u]++;
 44             low[u]=min(low[u],low[v]);
 45         }
 46         else if(fa[u] != v)
 47             low[u]=min(dfn[v],low[u]);
 48     }
 49 }
 50 void Solve()
 51 {
 52     int k=0;
 53     DFS(1,-1,k);
 54     int ans=0;
 55     for(int i=1;i <= 1000;++i)
 56     {
 57         //特判根节点 
 58         if(i == 1 && artPoint[1] <= 1)
 59             continue;
 60             
 61         //对于割点i,artPoint[i]:将其删去后,其儿子所形成的联通子图个数
 62         //+1:加上其父亲的联通子图 
 63         if(artPoint[i] > 0)
 64         {
 65             ans++;
 66             printf("  SPF node %d leaves %d subnets\n",i,artPoint[i]+(i != 1));
 67         }
 68     }
 69     if(ans == 0)
 70         printf("  No SPF nodes\n");
 71 }
 72 void Init()
 73 {
 74     num=0;
 75     mem(head,-1);
 76     mem(vis,false);
 77     mem(artPoint,0);
 78 }
 79 int main()
 80 {
 81     //freopen("C:/Users/hyacinthLJP/Desktop/stdin/contest","r",stdin);
 82     int u,v;
 83     int kase=1;
 84     bool flag=false;
 85     while(~scanf("%d",&u) && u)
 86     {
 87         Init();
 88         scanf("%d",&v);
 89         addEdge(u,v);
 90         addEdge(v,u);
 91         while(~scanf("%d",&u) && u)
 92         {
 93             scanf("%d",&v);
 94             addEdge(u,v);
 95             addEdge(v,u);
 96         }
 97         if(flag)
 98             printf("\n");
 99         flag=true;
100         
101         printf("Network #%d\n",kase++);
102         Solve();
103     }
104     
105     return 0;
106 }
View Code

 

转载于:https://www.cnblogs.com/violet-acmer/p/10580306.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值