zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    测开之路九十九:js函数、事件、window窗体对象
    测开之路九十八:js变量和语句
    测开之路九十七:js的引用方式
    学生管理之登录实现
    学生管理之表单设计
    二、Django用户认证之cookie和session
    一、Django前后端交互之Ajax和跨域问题
    中间介
    Java SE之反射技术[Class](三)
    Java SE之反射技术[Field](二)
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12129644.html
Copyright © 2011-2022 走看看