analysis
首先将题面简化,问题就成为:给一个有向图,有一些特殊点有权值,其他点都没有权值,选取特殊点中的一部分使得其权值和最小且其与其相连的点构成的集合等价于所有点构成的集合(语文差,没办法)
考虑简化问题,即将环缩成点,然后再做考虑(注意缩点的时候新点的权值要是旧点中的最小值,且还要维护一个点中序号最小标记)
缩点后,发现问题就转化为对图中以特殊点为起点的链的染色,由于链会重合,故可以贪心的对特殊点的权值排序,然后以升序对链染色,统计链的起点权值和和染色的点个数(话说这题好像不用建新图,但建了新图后会方便一点吧)
对问题的正确表述常常是解决问题的关键
边写代码边输出中间变量可以减少错误率
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll long long
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
int n,p,r,cnt=0,num=0;
const int maxn=3000+10,maxr=8000+10;
struct node{int e;int nxt;}edge[maxr];
int val_pson[maxn];
int val_t[maxn];
int head[maxn];
inline void addl(int u,int v){
edge[cnt].e=v;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
int dfn[maxn],low[maxn],belong[maxn],st[maxn],top=0,numoft=0,min_t[maxn];
void tarjan(int u){
low[u]=dfn[u]=++num;st[++top]=u;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[v],low[u]);
}else if(!belong[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
belong[u]=++numoft;
if(val_pson[u]<1061109567)val_t[numoft]=min(val_pson[u],val_t[numoft]);
min_t[numoft]=min(min_t[numoft],u);
while(st[top]!=u){
belong[st[top]]=numoft;
if(val_pson[st[top]]<1061109567)val_t[numoft]=min(val_pson[st[top]],val_t[numoft]);
min_t[numoft]=min(min_t[numoft],st[top]);
--top;
}--top;
}
}
struct line{int xi;int yi;}e[maxr];
inline bool cmp(line ai,line bi){return ((ai.xi==bi.xi)?ai.xi<bi.xi:ai.yi<bi.yi);}
inline void reset(){
loop(i,1,r){
e[i].xi=belong[e[i].xi];
e[i].yi=belong[e[i].yi];
}sort(e+1,e+1+r,cmp);
}
int in[maxn];int out[maxn];
inline void rebuild(){
reset();clean(in,0);clean(out,0);
cnt=0;clean(head,-1);
loop(i,1,r){
if(e[i].xi!=e[i].yi&&(e[i].xi!=e[i-1].xi||e[i].yi!=e[i-1].yi)){
addl(e[i].xi,e[i].yi);++in[e[i].yi];++out[e[i].xi];
}
}
}
int listofspy[maxn];
bool vis[maxn];
int sum=0;
int dfs(int pos){
int res=1;
for(int i=head[pos];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(vis[v])continue;
vis[v]=true;
res+=dfs(v);
}return res;
}inline bool cmp2(int a,int b){
if(val_pson[a]!=val_pson[b])return val_pson[a]<val_pson[b];
else return out[belong[a]]<out[belong[b]];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif // ONLINE_JUDGE
clean(head,-1);clean(dfn,0),clean(low,0);clean(min_t,0x3f);
read(n),read(p);clean(val_pson,0x3f);clean(vis,false);clean(val_t,0x3f);
loop(i,1,p){
int pos,num;
read(pos),read(num);listofspy[i]=pos;
val_pson[pos]=num;
}read(r);
loop(i,1,r){
read(e[i].xi),read(e[i].yi);
addl(e[i].xi,e[i].yi);
}loop(i,1,n)
if(!dfn[i])tarjan(i);
rebuild();
sort(listofspy+1,listofspy+1+p,cmp2);
int _cnt=0;
loop(i,1,p){
if(in[belong[listofspy[i]]]==0&&!vis[belong[listofspy[i]]])
vis[belong[listofspy[i]]]=true,sum+=val_t[belong[listofspy[i]]],_cnt+=dfs(belong[listofspy[i]]);
}
if(_cnt<numoft){
_cnt=INT_MAX;
loop(i,1,numoft)if(!vis[i]&&val_t[i]>=1061109567)_cnt=min(_cnt,min_t[i]);
printf("NO\n%d\n",_cnt);
}else printf("YES\n%d\n",sum);
return 0;
}