给出一个有向图,
A任务:求最少需要从几个点送入信息,使得信息可以通过有向图走遍每一个点
B任务:求最少需要加入几条边,使得有向图是一个强联通分量
任务A,比较好想,可以通过tarjan缩点,求出入度为0的点的个数
任务B
一开始以为任务A,B没有关系
其实是入度为0的点的个数、出度为0的点的个数的最大值。
因为任务B要求在任意学校投放软件使得所有学校都能收到,所以很明显是需要整张图形成一个环,而环中所有节点入度和出度都不为0,所以需要把所有入度和出度的点度数增加。
(注意判断本身就全联通的情况
#include <algorithm>#include <iterator>#include <iostream>#include <cstring>#include <cstdlib>#include <iomanip>#include <bitset>#include <cctype>#include <cstdio>#include <string>#include <vector>#include <stack>#include <cmath>#include <queue>#include <list>#include <map>#include <set>#include <cassert>/* ⊂_ヽ \\ Λ_Λ 来了老弟 \(‘?‘) > ⌒ヽ / へ\ / / \\ ? ノ ヽ_つ / / / /| ( (ヽ | |、\ | 丿 \ ⌒) | | ) /‘ノ ) L?*/using namespace std;#define lson (l , mid , rt << 1)#define rson (mid + 1 , r , rt << 1 | 1)#define debug(x) cerr << #x << " = " << x << "\n";#define pb push_back#define pq priority_queuetypedef long long ll;typedef unsigned long long ull;//typedef __int128 bll;typedef pair<ll ,ll > pll;typedef pair<int ,int > pii;typedef pair<int,pii> p3;//priority_queue<int> q;//这是一个大根堆q//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q#define fi first#define se second//#define endl ‘\n‘#define boost ios::sync_with_stdio(false);cin.tie(0)#define rep(a, b, c) for(int a = (b); a <= (c); ++ a)#define max3(a,b,c) max(max(a,b), c);#define min3(a,b,c) min(min(a,b), c);const ll oo = 1ll<<17;const ll mos = 0x7FFFFFFF; //2147483647const ll nmos = 0x80000000; //-2147483648const int inf = 0x3f3f3f3f;const ll inff = 0x3f3f3f3f3f3f3f3f; //18const int mod = 1e9+7;const double esp = 1e-8;const double PI=acos(-1.0);const double PHI=0.61803399; //黄金分割点const double tPHI=0.38196601;template<typename T>inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x=f?-x:x;}inline void cmax(int &x,int y){if(x<y)x=y;}inline void cmax(ll &x,ll y){if(x<y)x=y;}inline void cmin(int &x,int y){if(x>y)x=y;}inline void cmin(ll &x,ll y){if(x>y)x=y;}/*-----------------------showtime----------------------*/ const int maxn = 109; vector<int>mp1[maxn],mp2[maxn]; int dfn[maxn],low[maxn],vis[maxn],col[maxn]; int dp[maxn][maxn], in[maxn]; stack<int>st; int tot = 0,nn = 0; void tarjan(int u){ dfn[u] = low[u] = ++tot; st.push(u); vis[u] = 1; for(int i=0; i<mp1[u].size(); i++){ int v = mp1[u][i]; if(dfn[v] == 0){ tarjan(v); low[u] = min(low[u], low[v]); } else if(vis[v]){ low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]){ nn++; while(!st.empty()){ int x = st.top(); st.pop(); col[x] = nn; vis[x] = 0; if(x == u) break; } } } int main(){ int n; scanf("%d", &n); rep(i, 1, n){ int x; while(~scanf("%d", &x) && x) mp1[i].pb(x); } rep(i, 1, n) if(!dfn[i]) tarjan(i); rep(i, 1, n) { int u = col[i]; for(int j=0; j<mp1[i].size(); j++){ int v = col[mp1[i][j]]; dp[u][v] = 1; } } rep(i, 1, nn) { rep(j, 1, nn) { if(i == j) continue; if(dp[i][j]) mp2[i].pb(j), in[j]++; } } int ansa = 0,c1=0,c2=0; rep(i, 1, nn) { if(in[i] == 0) ansa++,c1++; if(mp2[i].size() == 0) c2 ++; } if(nn == 1) c1 = c2 = 0; printf("%d\n%d\n", ansa,max(c1, c2)); return 0;}
View Code