#10091. 「一本通 3.5 例 1」受欢迎的牛
Tarjan 经常和topsort联系起来考察,非常好的DAG DAG图上处理问题会变得很爽
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int,int>;
const int N = 2e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
int gcd(int a,int b){return b?a:gcd(b,a%b);}
int lcm(int a,int b){return a*b/gcd(a,b);}
int qmi(int a,int b,int mod){int res=1;while(b){if(b&1)res=res*a%mod;b>>=1;a=a*a%mod;}return res;}
int n,q,m;
int e[N],ne[N],w[N],h[N],idx;
void add(int a,int b,int c=0){
e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
}
int dfn[N],low[N],timestamp;
int scc_cnt,sz[N],id[N];
int stk[N],top;
int dout[N];
bool in_stk[N];
void tarjan(int u)
{
dfn[u] = low[u] = ++timestamp;
in_stk[u] = true;stk[++top] = u;
for(int i=h[u];~i;i=ne[i]){
int j = e[i];
if(!dfn[j]){
tarjan(j);low[u] = min(low[u],low[j]);
}else if(in_stk[j])low[u] = min(low[u],dfn[j]);
}
if(low[u]==dfn[u]){
int y;
++scc_cnt;
do{
y = stk[top--];
in_stk[y] = false;
id[y] = scc_cnt;
sz[scc_cnt]++;
}while(y!=u);
}
}
void solve()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
int a,b;cin>>a>>b;
add(a,b);
}
for(int i=1;i<=n;i++)if(!dfn[i]){tarjan(i);}
for(int i=1;i<=n;i++){
for(int j=h[i];~j;j=ne[j]){
int k = e[j];
if(id[i]==id[k])continue;
dout[id[i]]++;
}
}
//cout<<scc_cnt<<"\n";
int f=0;
int ans = 0;
for(int i=1;i<=scc_cnt;++i){
if(!dout[i]){
f++;
ans+=sz[i];
}
}
if(f>1)cout<<0;
else cout<<ans;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _;
//cin>>_;
_ = 1;
while(_--)solve();
return 0;
}
#10094. 「一本通 3.5 练习 2」消息的传递
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int,int>;
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
int gcd(int a,int b){return b?a:gcd(b,a%b);}
int lcm(int a,int b){return a*b/gcd(a,b);}
int qmi(int a,int b,int mod){int res=1;while(b){if(b&1)res=res*a%mod;b>>=1;a=a*a%mod;}return res;}
int n,q,m;
int e[N],ne[N],w[N],h[N],idx;
void add(int a,int b,int c=0){
e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
}
int dfn[N],low[N],times;
bool in_stk[N];
int stk[N],top;
int scc_cnt,sz[N],id[N];
int din[N],dout[N];
void tarjan(int u)
{
dfn[u] = low[u] = ++times;
in_stk[u] = true;stk[++top] = u;
for(int i=h[u];~i;i=ne[i]){
int j = e[i];
if(!dfn[j]){
tarjan(j);low[u] = min(low[u],low[j]);
}else if(in_stk[j])low[u] = min(low[u],dfn[j]);
}
if(dfn[u]==low[u]){
int y;++scc_cnt;
do{
y = stk[top--];
id[y] = scc_cnt;
sz[scc_cnt]++;
in_stk[y] = false;
}while(y!=u);
}
}
void solve()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int x;cin>>x;
if(x)add(i,j);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
for(int a=1;a<=n;a++){
for(int i=h[a];~i;i=ne[i]){
int b = e[i];
if(id[a]==id[b])continue;
din[id[b]]++;
}
}
int res = 0;
for(int i=1;i<=scc_cnt;++i){
if(!din[i])res++;
}
cout<<res<<"\n";
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _;
//cin>>_;
_ = 1;
while(_--)solve();
return 0;
}
#10095. 「一本通 3.5 练习 3」间谍网络
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
using pii = pair<int,int>;
const int N = 1e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
int gcd(int a,int b){return b?a:gcd(b,a%b);}
int lcm(int a,int b){return a*b/gcd(a,b);}
int qmi(int a,int b,int mod){int res=1;while(b){if(b&1)res=res*a%mod;b>>=1;a=a*a%mod;}return res;}
int n,q,m;
int e[N],ne[N],w[N],h[N],idx;
void add(int a,int b,int c=0){
e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
}
int dfn[N],low[N],times;
bool in_stk[N];
int stk[N],top;
int scc_cnt,sz[N],id[N];
int din[N],dout[N];
int cost[N],wss[N];
int ids[N];
vector<int>topsort;
void tarjan(int u)
{
dfn[u] = low[u] = ++times;
in_stk[u] = true;stk[++top] = u;
for(int i=h[u];~i;i=ne[i]){
int j = e[i];
if(!dfn[j]){
tarjan(j);low[u] = min(low[u],low[j]);
}else if(in_stk[j])low[u] = min(low[u],dfn[j]);
}
if(dfn[u]==low[u]){
int y;++scc_cnt;
do{
y = stk[top--];
id[y] = scc_cnt;
sz[scc_cnt]++;
topsort.push_back(y);
cost[scc_cnt] = min(cost[scc_cnt],wss[y]);
ids[scc_cnt] = min(ids[scc_cnt],y);
in_stk[y] = false;
}while(y!=u);
}
}
int res;
void solve()
{
cin>>n;
memset(h,-1,sizeof h);
memset(wss,0x3f,sizeof wss);
memset(cost,0x3f,sizeof cost);
memset(ids,0x3f,sizeof ids);
cin>>q;
for(int i=1;i<=q;i++){
int x,cs;cin>>x>>cs;
wss[x] = cs;
}
cin>>m;
while(m--){
int a,b;cin>>a>>b;
add(a,b);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
reverse(topsort.begin(),topsort.end());
for(int &a:topsort){
for(int i=h[a];~i;i=ne[i]){
int b = e[i];
if(id[a]==id[b]||cost[id[a]]>inf/2)continue;
din[id[b]]++;
cost[id[b]] = 0;
}
}
for(int i=1;i<=scc_cnt;++i){
if(!din[i]){
res+=cost[i];
if(res>inf)break;
}
}
if(res<inf/2){
cout<<"YES\n";cout<<res;return;
}
int idss = n+1;
for(int i=1;i<=scc_cnt;++i){
if(!din[i]&&cost[i]>inf/2){
idss = min(idss,ids[i]);
}
}
cout<<"NO\n";
cout<<idss;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _;
//cin>>_;
_ = 1;
while(_--)solve();
return 0;
}