套上双联通分量的板子
标记一个爹
然后map记一下
舒服
#include<bits/stdc++.h>
using namespace std;
vector<int>tu[101];
int liantong[10100], dfn[10100], low[10100], clj = 0, jc = 0;
stack<int>zz;
map<int,int>mp[10100];
void tarjan(int xianzai,int ba)
{
dfn[xianzai] = low[xianzai] = ++clj;
zz.push(xianzai);
for (int a = 0;a<tu[xianzai].size();a++)
{
int dd = tu[xianzai][a];
if (!dfn[dd])
{
tarjan(dd,xianzai);
low[xianzai] = min(low[xianzai], low[dd]);
}
else if(dd!=ba)
{
if (!liantong[dd])low[xianzai] = min(low[xianzai], low[dd]);
}
}
if (low[xianzai] == dfn[xianzai])
{
jc++;
for (;;)
{
int ww = zz.top();
zz.pop();
liantong[ww] = jc;
if (ww == xianzai)break;
}
}
}
struct p
{
int z,y;
bool operator < (const p&a)const{
if(z==a.z)return y<a.y;
return z<a.z;
}
};
p dan[1000000];
int main()
{
int n;
while(cin>>n)
{
while(!zz.empty())zz.pop();
for(int a=0;a<n;a++)tu[a].clear();
memset(liantong,0,sizeof(liantong));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
clj=0,jc=0;
memset(dan,0,sizeof(dan));
for(int a=1;a<=n;a++)
{
int q,w,e;
scanf("%d (%d)",&q,&w);
for(int b=1;b<=w;b++)
{
scanf("%d",&e);
tu[q].push_back(e);
}
}
for(int a=0;a<n;a++)
{
if(dfn[a])continue;
tarjan(a,-1);
}
for(int a=0;a<=n;a++)mp[a].clear();
int we=0;
for(int a=0;a<n;a++)
{
for(int b=0;b<tu[a].size();b++)
{
int yy=tu[a][b];
if(liantong[a]==liantong[yy])continue;
if(mp[liantong[a]][liantong[yy]])continue;
if(mp[liantong[yy]][liantong[a]])continue;
mp[liantong[yy]][liantong[a]]=mp[liantong[a]][liantong[yy]]=1;
dan[++we]={a,yy};
}
}
printf("%d critical links\n",we);
for(int a=1;a<=we;a++)
{
printf("%d - %d\n",dan[a].z,dan[a].y);
}
printf("\n");
}
}