1. 迷路の城
質問が意図されています。図に強く連結グラフかどうかを決定します。
図面強連結成分を使用してTarjan数計算、及び一方が強連結グラフであれば、そうでない場合はない:溶液。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e4+100;
typedef long long ll;
vector<int> G[N];
bool is_instack[N];
int dfn[N],low[N];
stack<int> sta;
int n,m,index,scc;
void init(){
index=scc=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(is_instack,0,sizeof(is_instack));
while(!sta.empty()) sta.pop();
for(int i=1;i<=n;i++) G[i].clear();
}
void Tarjan(int u){
dfn[u]=low[u]=++index;
sta.push(u);is_instack[u]=1;
for(auto v:G[u]){
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
++scc;
while(sta.top()!=u){
is_instack[sta.top()]=0;
sta.pop();
}
}
}
int main(){
while(scanf("%d %d",&n,&m)){
if(n+m==0) break;
init();
int u,v;
for(int i=0;i<m;i++){
scanf("%d %d",&u,&v);
G[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) Tarjan(i);
}
if(scc==1) puts("Yes");
else puts("No");
}
return 0;
}
2. 証明それに相当します
問題の意味:有向グラフを考えると、最小シークプラス全体図は、強連結になるように、いくつかの方向のエッジ。
溶液:Tarjanとして顕著点算出凝縮後\(0 \)数\(A \)との程度\(0 \)数\(Bを\) 、最大値をとる(MAX(\ B)\)、あなたは強連結グラフを持っている、と答えがある場合ことに注意してください(0 \)\。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
vector<int> G[N],color[N];
stack<int> sta;
int dfn[N],low[N];
int id[N],od[N];
bool is_instack[N];
int scc[N],nscc,index;
int n,m;
void init(){
nscc=index=0;
memset(scc,0,sizeof(scc));
memset(dfn,0,sizeof(dfn));
memset(id,0,sizeof(id));
memset(od,0,sizeof(od));
memset(is_instack,0,sizeof(is_instack));
memset(low,0,sizeof(low));
for(int i=1;i<=n;i++) G[i].clear(),color[i].clear();
while(!sta.empty()) sta.pop();
}
void Tarjan(int u){
low[u]=dfn[u]=++index;
sta.push(u);is_instack[u]=1;
for(auto v:G[u]){
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
++nscc;
while(1){
int temp=sta.top();
scc[temp]=nscc;
sta.pop();
is_instack[temp]=0;
if(temp==u) break;
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
init();
int u,v;
for(int i=1;i<=m;i++){
scanf("%d %d",&u,&v);
G[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) Tarjan(i);
}
//cerr<<nscc<<endl;
if(nscc==1){
puts("0");
}
else{
for(int i=1;i<=nscc;i++) id[i]=od[i]=1;
for(int i=1;i<=n;i++){
for(auto j:G[i]){
if(scc[i]!=scc[j]){
id[scc[j]]=od[scc[i]]=0;
}
}
}
int n1=0;int n2=0;
for(int i=1;i<=nscc;i++){
n1+=id[i];n2+=od[i];
}
printf("%d\n",max(n1,n2));
}
}
return 0;
}
3. 夏休み
質問の意味:あなたを与えるために、あなたはいくつかのポイントを選択する必要があり、これらの点の使用が完全にA有向グラフをトラバースすることができ作る、各点は、この図に重みを持っていますが、またこれらの選択を満たします重量および極小点。
解釈:Tarjan凝縮点、及び最小の減少点れるの強連結成分収縮点の重量重み、およびゼロ度ポイント数、すなわち、回答を探し。
{%がフォールド明示的/暗黙コンテンツ%をクリック}
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n,m,scc,index;
vector<int> G[N];
ll w[N],low[N],dfn[N],minn[N],color[N],id[N];
bool is_instack[N];stack<int> sta;
void init(){
scc=index=0;
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(color,0,sizeof(color));
memset(minn,INF,sizeof(minn));
memset(is_instack,0,sizeof(is_instack));
for(int i=1;i<=n;i++) G[i].clear();
while(!sta.empty()) sta.pop();
}
void Tarjan(int u){
low[u]=dfn[u]=++index;
sta.push(u);is_instack[u]=1;
for(auto v:G[u]){
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
++scc;
while(1){
int temp=sta.top();
color[temp]=scc;
minn[scc]=min(minn[scc],w[temp]);
is_instack[temp]=0;
sta.pop();
if(temp==u) break;
}
}
}
int main(){
while(scanf("%d %d",&n,&m)!=EOF){
init();
for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d %d",&u,&v);
G[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) Tarjan(i);
}
for(int i=1;i<=scc;i++) id[i]=1;
for(int i=1;i<=n;i++){
for(auto j:G[i]){
if(color[i]!=color[j]){
id[color[j]]=0;
}
}
}
ll ans1,ans2;ans1=ans2=0;
for(int i=1;i<=scc;i++){
if(id[i]){
ans1++;
ans2+=minn[i];
}
}
printf("%lld %lld\n",ans1,ans2);
}
return 0;
}
{%}%Endfold
4. 知能システム
質問の意味:関係のネットワーク、任意の1人で0接触、2人が互いに直接または間接的に接触することができた場合、0の2人の男性の消費、0人あたりの最小消費に連絡しようとします。
解釈:Tarjan集点は、それが最小限の重量に対する各エッジ点のためにのみ必要な統計である、溶液を確実にするために、被験体から、最小の木を見つけます。考えられない0強連結成分。
#include<bits/stdc++.h>
using namespace std;
const int N = 50005 ;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
ll low[N],dfn[N],minn[N],color[N];
bool is_instack[N];
ll n,m,scc,index;
stack<ll> sta;
vector<pair<ll,ll> > G[N];
void init(){
scc=index=0;
for(int i=0;i<=n;i++){
is_instack[i]=0;
low[i]=0;
dfn[i]=0;
minn[i]=INF;
G[i].clear();
}
while(!sta.empty()) sta.pop();
}
void Tarjan(ll u){
low[u]=dfn[u]=++index;
is_instack[u]=1;sta.push(u);
for(auto V:G[u]){
ll v=V.first;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
scc++;
while(1){
ll temp=sta.top();
color[temp]=scc;
is_instack[temp]=0;
sta.pop();
if(temp==u) break;
}
}
}
int main(){
while(scanf("%lld %lld",&n,&m)!=EOF){
map<pair<ll,ll>,ll> WW;
//pair<ll,ll> pnow;
init();
ll u,v,w;
for(ll i=1;i<=m;i++){
scanf("%lld %lld %lld",&u,&v,&w);
//pnow.first=u;pnow.second=v;
//if(!WW[pnow]) WW[pnow]=w;
//else WW[pnow]=min(WW[pnow],w);
G[u].push_back(make_pair(v,w));
}
long long ans=0;
for(ll i=0;i<n;i++){
if(!dfn[i]) Tarjan(i);
}
for(ll i=0;i<n;i++){
for(auto j:G[i]){
ll x=color[i];
ll y=color[j.first];
if(x!=y) minn[y]=min(minn[y],(ll)j.second);
}
}
for(ll i=1;i<=scc;i++){
if(i!=color[0]) ans+=minn[i];
}
printf("%lld\n",ans);
}
return 0;
}