signedmain(){ fastio(); int T; cin>>T; while(T--){ int n, a, b; cin>>n>>a>>b; if(n-a-b>1||(a==n&&b==n)) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return0; }
First of all, we need to check if the graph is already connected at
the beginning. If so, the answer would be 0.
Otherwise, there will be more than connected component. If there exists a
vertex that is the only vertex required to be operated to make the graph
connected, we call such a vertex "feasible vertex". We may find out that
a feasible vertex can only appear in a connected component that is not a
clique.
But actually, there will always be such a vertex in a non-clique
component. To prove this, we may figure out the sufficient condition for
being a feasible vertex first.
The sufficient condition is that, if a vertex is not a cut vertex,
and it is not adjacent to all other vertices in the connected component,
then it must be a feasible vertex. We can prove that such a vertex
always exists in a non-clique component. Here is the proof:
Firstly, if there exist vertices that are adjacent to all other
vertices in the component, we erase all of them.
Apparently, the remaining component would still be a non-clique
component. Otherwise, the component could only be a clique from the
beginning, which contradicts the premise.
Then, we will find a non-cut vertex in the remaining component,
since that vertices in a graph couldn't be all cut vertices. The non-cut
vertex we found is the vertex we are searching for.
But implementing it directly (meaning using Tarjan's algorithm to
find a non-cut vertex) might not be the easiest way to solve the
problem. Actually, there are two other ways we have found so far to
solve the problem alternatively. The first one is that we can simply
output the vertex with the least degree in a connected component; the
other one is that we can do DFS in a connected component and output the
last visited vertex (as long as the connected component is not a
clique). We would like to leave the proof work of these two alternative
ways to you.
Now we have proven that, if there exists a connected component that
is not a clique, then the answer would be at most . What if all connected components are
cliques?
If there are exactly connected
components, then apparently we will have to operate on all vertices in a
connected component. So we'll choose the smaller connected component to
operate, and the answer is exactly the size of it.
Otherwise, we can arbitrarily choose two vertices from two different
connected components and operate on them. The answer is .
Note that we also need to deal with isolated vertices (meaning
vertices that are not adjacent to any other vertices) separately.
constexprint N = 4005; int n; int deg[N]; int fa[N]; int c[N]; vector<int> v[N]; vector<int> cv; intfind(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
voidsolve() { cin >> n; Fe(i, 1, n) fa[i] = i, c[i] = 0, deg[i] = 0; Fe(i, 1, n) Fe(j, 1, n) { char o; cin >> o; if (o == '1') { int x = find(i), y = find(j); if (x != y) c[y] += c[x], fa[x] = y; c[find(j)]++; deg[i]++; } } cv.clear(); Fe(i, 1, n) v[i].clear(); Fe(i, 1, n) v[find(i)].pb(i); Fe(i, 1, n) if (fa[i] == i) cv.pb(i); if (cv.size() == 1) { cout << 0 << endl; return; } Fe(i, 1, n) if (fa[i] == i) { if (deg[i] == 0 || c[i] != v[i].size() * (v[i].size() - 1)) { int p = 0; for (int u : v[i]) if (!p || deg[u] < deg[p]) p = u; cout << "1\n" << p << endl; return; } } if (cv.size() > 2) { cout << "2\n" << v[cv[0]].back() << ' ' << v[cv[1]].back() << endl; return; }
if (v[cv[0]].size() > v[cv[1]].size()) swap(cv[0], cv[1]); cout << (int)v[cv[0]].size() << endl; for (int u : v[cv[0]]) cout << u << ' '; cout << "\n"; }