問題の説明
「はい、はい!そう、まだ次の問題のための準備ができていますか?」白フラッシュ、日中韓1e100は、小学校の前に現れました。「一部の人々は私のマシンを追跡する彼ら、今、私は1Sでそれらを見つけるためにあなたを必要とし、それらを認めなければならない!」全知の神ご自身(玄)奇数(雪)力、日中韓ですぐに私たちは、学生のマシンのJesseLiunをn型追跡することがわかりました。しかし、彼は認めざるを得ない生徒を支援する方法を見つける必要があります。p個の小学生が、価格で購入することを望んながら幸いにも、CJK糖の無限の数があります。そして、生徒間のR BiShi関係があります。瞳が購入された後、彼は認めるためのイニシアチブをとるだろう、と彼は認めるためにそれらを強制的に、情報提供者BiShi。認めることを余儀なくされている人たちは、彼がそうで情報提供者、およびをBiShiます。
入力形式
二つの数、nおよびpの最初の行。そして、p行、二つの数xとyの1、xがyの価格で購入することに喜んで学生の数を表します。次の行は、その数は、小学校の生徒のx個のyのBiShi(もちろん、これはYの数だろうBiShi番号xを意味するものではないM、m行続いて、二つの数xとyとのそれぞれでありますA)。
出力フォーマット
すべてのn CJKは「YES」、生徒が認め出力を作り、お菓子コストの出力に必要な最小数の次の行場合。ない場合は、出力が「NO」、および次の最小出力回線番号、および生徒を認めません。
サンプル入力と出力
サンプル入力1
3
2
1 10
2 100
2
1 3
2 3
サンプル出力1
YES
110
サンプル入力2
4
2
1 100
4 200
2
1 2
3 4
サンプル出力2
NO
3
解決
正解は、縮合環Tarjanで、新しいポイントは右のリング最小動的プログラミングして、DAGです。ポイントは他のポイントに達することができるなら、この点を選択する必要はありません。
検査室にTarjanのを忘れているので、一時的な練習を思い付いた、ほぼすべてのポイントは、互いの二つの重要な点は環を示すことができる場合は、最初、ポイントすることによって達成することができるDFSつつ統計点、上記同じロジックを実行することですこの時点で最小値をとります。それ以外の場合は、ポイントの反対側に到達することができました。
コード
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 3002
#define M 20002
using namespace std;
int head[N],ver[M],nxt[M],l;
int m,n,p,w[N],i,j,f[N],g[N],a[N];
bool vis[N],e[N][N],key[N];
void insert(int x,int y)
{
l++;
ver[l]=y;
nxt[l]=head[x];
head[x]=l;
}
int min(int x,int y)
{
if(w[x]<w[y]) return x;
return y;
}
void dfs(int x,int node)
{
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(!vis[y]){
e[node][y]=1;
dfs(y,node);
}
}
}
void dp(int x,int kid)
{
if(vis[x]) return;
vis[x]=1;
if(f[x]==0) f[x]=kid;
else if(e[kid][f[x]]&&!e[f[x]][kid]) f[x]=kid;
else if(e[kid][f[x]]&&e[f[x]][kid]) f[x]=min(f[x],kid);
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(f[y]!=kid) dp(y,kid);
}
}
int main()
{
freopen("pupil.in","r",stdin);
freopen("pupil.out","w",stdout);
cin>>n>>p;
for(i=1;i<=p;i++){
int x;
cin>>a[i]>>x;
w[a[i]]=x;
}
cin>>m;
for(i=1;i<=m;i++){
int u,v;
cin>>u>>v;
insert(u,v);
}
for(i=1;i<=n;i++) e[i][i]=1;
for(i=1;i<=p;i++){
memset(vis,0,sizeof(vis));
dfs(a[i],a[i]);
}
for(i=1;i<=p;i++){
memset(vis,0,sizeof(vis));
dp(a[i],a[i]);
}
int ans=0;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++){
if(f[i]==0){
cout<<"NO"<<endl<<i<<endl;
return 0;
}
else if(!vis[f[i]]) ans+=w[f[i]],vis[f[i]]=1;
}
cout<<"YES"<<endl<<ans<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
泥棒は遅く走った......