HDU-3836
題目
題目大意
把這個圖變成強聯通圖需要加多少條邊
思路
tarjan縮點然後加邊,但是我不知道怎麼加,查了一下題解說是要每個點出入度>=1,一開始很不解爲什麼,後面發現這是單向條件,就是說雖然每個點出入度大於等於1的圖不一定是強連通圖,但是強聯通圖每個點出入度必是大於等於一的,因爲這樣纔可以保證每個點可以到達他(所以入度>=1,因爲要有一個入口),他可以達到所有點(所以出度>=1,因爲要有一個出口),最後特判只有一個scc的時候,其他情況就是出入度爲0數去max
代碼
#include <iostream>
#include <cstdio>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <unordered_map>
using namespace std;
#define dbg(x) cerr << #x " = " << x << endl;
typedef pair<int, int> P;
typedef long long ll;
const int MAXN = 2e4 + 5;
const int MAXM = 5e4+5;
struct Edge
{
int to ,next;
}edge[MAXM];
int head[MAXN], tot;
int Low[MAXN], DFN[MAXN], num[MAXN], Belong[MAXN];
int scc;
int Stack[MAXN];
bool Instack[MAXN];
int Index, top;
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if(!DFN[v])
{
tarjan(v);
Low[u] = min(Low[u], Low[v]);
}
else if(Instack[v])
{
Low[u] = min(Low[u], DFN[v]);
}
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = 0;
num[scc]++;
Belong[v] = scc;
}while(u != v);
}
}
void solve(int N)
{
memset(DFN, 0, sizeof(DFN));
memset(Instack, 0, sizeof(Instack));
memset(num, 0, sizeof(num));
Index = scc = top = 0;
for(int i = 1; i <= N; i++)
{
if(!DFN[i]) tarjan(i);
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m;
while(scanf("%d%d", &n ,&m) == 2)
{
init();
vector<P> s;
for(int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
s.push_back(P(u, v));
}
solve(n);
int ans = 0;
int In[MAXN] = {0}, Out[MAXN] = {0};
for(int i = 0; i < s.size(); i++)
{
int u = s[i].first;
int v = s[i].second;
if(Belong[u] != Belong[v])
{
Out[Belong[u]]++;
In[Belong[v]]++;
}
}
int ans1 = 0, ans2 = 0;
for(int i = 1; i <= scc; i++)
{
if(!In[i]) ans1++;
if(!Out[i]) ans2++;
}
if(scc == 1) cout << 0 << endl;
else cout << max(ans1, ans2) << endl;
}
}