洛谷 P1262 间谍网络 【强连通缩点】

题目链接

题意:

太长了自己看

题解:

缩点,每个强连通分量的最小价格就是分量中所有点最小的价格,再根据贪心,只有那些不能被其他强连通分量到的分量才需要买

#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;

#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))

const int mod = 1e9+7;
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
int dfn[3005],low[3005],s[3005],vis[3005],in[3005],w[3005],col[3005],minw[3005];
int n,p,sum,tim,tp,cnt; 
vector<int>g[3005];
int g2[3005][3005];
void tarjan(int u){
	dfn[u]=low[u]=++tim,s[++tp]=u,vis[u]=1;
	for(auto v:g[u]){
		if(!dfn[v]){
			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]){
		int x,miw=INF; cnt++;
		do{
			x=s[tp--],vis[x]=0,col[x]=cnt,miw=min(miw,w[x]);
		}while(u!=x);
		minw[cnt]=miw;
	}
}
#define endl '\n'
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>p;
	for(int i=1;i<=n;i++)w[i]=INF;
	for(int i=1;i<=p;i++){
		int id,cost; cin>>id>>cost; 
		w[id]=cost;
	}
	int m; cin>>m;
	for(int i=1;i<=m;i++){
		int u,v; cin>>u>>v;
		g[u].push_back(v),in[v]++;
	}
	for(int i=1;i<=n;i++)
		if(!in[i]&&w[i]==INF){cout<<"NO"<<endl<<i<<endl; return 0;}
		else in[i]=0;
	for(int i=1;i<=n;i++)if(!dfn[i]&&w[i]!=INF)tarjan(i);
	for(int u=1;u<=n;u++){
		for(auto v:g[u]){
			if(col[u]==col[v]||g2[col[u]][col[v]])continue;
			g2[col[u]][col[v]]=1;
			if(in[col[u]]||minw[col[u]]!=INF)in[col[v]]=1;
		}
	}
	int sum=0;
	for(int i=1;i<=cnt;i++){
		if(in[i])continue;
		sum+=minw[i];
	}
	cout<<"YES"<<endl<<sum<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值