题意:赤裸裸的求割点
在写题之前了解一下有关知识: 图的割点、桥与双连通分支 (日常%dalao)
看完差不多就可以开心的写了~
因为强连通针对有向图,而割点和桥和双连通是针对无向图的,所以必须分清,无向图中需要处理一下双向边,避免这种边造成什么影响,所以一般tarjan里会多一个参数pre,来标志当前u的爸爸。
这题就是求割点的模板题。(然而还是WA WAWA)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxn = 150;
const int maxe = 1e4;
char s[1500];
int h[maxn],dfn[maxn],low[maxn],isCut[maxn];
struct node
{
int to,next;
node(){}
node(int a,int b){to = a; next = b;}
}edge[maxe << 2];
int edgenum = 0,ans = 0,tot = 0;
int n;
void init()
{
for(int i = 1; i <= n ; i++)
h[i] = -1, dfn[i] = low[i] = isCut[i] = 0;
edgenum = ans = tot = 0;
}
void add(int f,int t)
{
edge[edgenum] = node(t,h[f]);
h[f] = edgenum ++;
}
void tarjan(int u,int father)
{
dfn[u] = low[u] = ++tot;
int child = 0;
for(int i = h[u]; ~i ; i = edge[i].next)
{
int v = edge[i].to;
if(!dfn[v])
{
child++;
tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v] >= dfn[u]) isCut[u] = 1;
}
else if(dfn[v] < dfn[u] && father != v)
low[u] = min(low[u],dfn[v]);
}
if(father == -1 && child == 1) isCut[u] = 0;
}
int main()
{
while(~scanf("%d",&n) && n)
{
init();
while(cin.getline(s,1500))
{
if(s[0] == '0') break;
stringstream ss;
ss << s;
int t,u,flag = 0;
while(ss >> t)
{
if(!flag) u = t,flag = 1;
else {add(u,t); add(t,u);}
}
}
//if(n == 1){printf("0\n"); continue;}
for(int i = 1; i <= n ; i++)
if(!dfn[i]) tarjan(i,-1);
for(int i = 1; i <= n ; i++) if(isCut[i] == 1) ans++;
printf("%d\n",ans);
}
return 0;
}