codeforce 427 C. Checkposts(tarjan 强连通分量)

题目链接:http://codeforces.com/contest/427/problem/C

题目大意是有n个junctions,这些junctions之间有m条道路,两两相连,现在在junction上建立Checkposts,而且建立checkposts需要花费cost,如果某个点 i 建立了checkpost那么从这个点 i 开始绕一个环最终可以回到点 i ,那么途中经过的点都可以被监视到,问最少花费多少钱去建立checkposts才可以监视所有的junctions,建立checkposts的方案有多少种?

题解思路:刨析题意就是让你求有多少个强连通分量,用tarjan依次跑出每个强连通分量包含的点集,找出该集合中建立checkposts的最小花费,再求一下可以用最小花费建checkpost的junction的个数,最终的方案书就是每个强连通分量的 最小花费建checkpost的junction的个数连乘,最小花费就简单了,求一个强连通分量就加一下最小花费即可。

AC代码:

#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
struct node{
	vector<int> vex;
	int cost;
};
node g[3000008];
int dfn[3000008];
int low[3000008];
int visit[3000008];
stack<int> stk;
vector<int> sum;
long long int Fcost = 0;
int tot ;
long long int mod = 1e9+7;
void tarjan(int x){
	dfn[x] = low[x] = ++tot;
	visit[x] = 1;
	stk.push(x);
	for(int i = 0;i<g[x].vex.size();i++ ){
		if(!dfn[g[x].vex[i]]){
			tarjan(g[x].vex[i]);
			low[x] = min(low[x],low[g[x].vex[i]]);
		}
		else if(visit[g[x].vex[i]]){
			low[x] = min(low[x],dfn[g[x].vex[i]]);
		}
		}
		if(low[x] == dfn[x]){//找到一个强连通分量 
			int cnt = 1;
			int Tcost = 0x3f3f3f3f;
			while(x!=stk.top()){
				visit[stk.top()] = 0;
				if(g[stk.top()].cost < Tcost){
					cnt = 1;//从这个强连通分量中找最小花费 
			        Tcost = min(Tcost,g[stk.top()].cost);		
				}
				else if(g[stk.top()].cost == Tcost){
					cnt++;//记录最小花费点的个数 
				}
				stk.pop();
			}
			visit[stk.top()] = 0;
			if(g[stk.top()].cost < Tcost)
			{
				cnt = 1;
			    Tcost = min(Tcost,g[stk.top()].cost);		
			}
			else if(g[stk.top()].cost == Tcost)
			{
				cnt++;
			}
			stk.pop();//这里是弹出栈内最后一个强连通分量的点 
			Fcost = (Fcost + Tcost);//Fcost是总花费 
			sum.push_back(cnt); //记录每个强连通分量的可以用最小花费点建立checkpost的个数 
		} 
}
int main(){
	int n;
	cin>>n;
	for(int i = 1;i<=n;i++){
		int costI;
		cin>>costI;
		g[i].cost = costI;
	}
	int m;
	cin>>m;
	for(int i = 1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		g[u].vex.push_back(v);  
	}
	for(int i = 1;i<=n;i++){//tarjan的板子,直接套一下 
		if(!dfn[i]){
			tarjan(i);
		}
	}
	long long int res = 1;
	for(int i = 0;i<sum.size();i++){
		res = (res*sum[i])%mod;
	}
	cout<<Fcost<<" "<<res;
	return 0;
}
原文地址:https://www.cnblogs.com/AaronChang/p/12129644.html