tarjan标准题。 直接tarjan即可。
思考一个问题:添加多少个边让图变为连通图。
Test 1: TEST OK [0.003 secs, 3512 KB] Test 2: TEST OK [0.003 secs, 3380 KB] Test 3: TEST OK [0.003 secs, 3512 KB] Test 4: TEST OK [0.005 secs, 3512 KB] Test 5: TEST OK [0.005 secs, 3512 KB] Test 6: TEST OK [0.005 secs, 3512 KB] Test 7: TEST OK [0.005 secs, 3512 KB] Test 8: TEST OK [0.008 secs, 3512 KB] Test 9: TEST OK [0.008 secs, 3512 KB] Test 10: TEST OK [0.005 secs, 3512 KB] Test 11: TEST OK [0.005 secs, 3512 KB]
/*
TASK:schlnet
LANG:C++
*/
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
vector<int>G[200];
int n;
int DFN[200] = {0}, LOW[200] = {0};
int instack[200] = {0}, my_stack[200] = {0};
int belong[200] = {0};
int Stop = 0, din = 0, count = 0;
void tarjan(int k)
{
LOW[k] = DFN[k] = ++ din;
my_stack[++ Stop] = k;
instack[k] = 1;
for (int i = 0; i != G[k].size(); ++ i)
{
int will = G[k][i];
if (!DFN[will])
{
tarjan(will);
LOW[k] = min(LOW[k], LOW[will]);
}
else if (instack[will]) LOW[k] = min(LOW[k], DFN[will]);
}
if (LOW[k] == DFN[k])
{
int tmp;
++ count;
do
{
tmp = my_stack[Stop --];
instack[tmp] = 0;
belong[tmp] = count;
}while (tmp != k);
}
}
int rudu[200] = {0}, chudu[200]={0};
int main()
{
//freopen("schlnet.in", "r", stdin);
//freopen("schlnet.out","w",stdout);
cin >> n;
for (int i = 0; i != n; ++ i)
{
while (1)
{
int tmp;
cin >> tmp;
if (!tmp) break;;
G[i].push_back(tmp - 1);
}
}
for (int i = 0; i != n; ++ i)
if (!DFN[i]) tarjan(i);
for (int i = 0; i != n; ++ i)
for (int j = 0; j != G[i].size(); ++ j)
{
int will = G[i][j];
if (belong[i] == belong[will]) continue;
++ rudu[belong[will]];
++ chudu[belong[i]];
}
int ans1 = 0, ans2 = 0;//ans1 几个地方发放就可以了 ans2要连接几个
for (int i = 1; i <= count; ++ i)
{
if (!chudu[i]) ++ans2;
if (!rudu[i]) ++ ans1;
}
cout<<ans1<<endl;
if (count > 1)cout<<max(ans1, ans2)<<endl;
else cout<<0<<endl;
return 0;
}