zoukankan      html  css  js  c++  java
  • BZOJ 1179 (Tarjan缩点+DP)

    题面

    传送门

    分析

    由于一个点可以经过多次,显然每个环都会被走一遍。
    考虑缩点,将每个强连通分量缩成一个点,点权为联通分量上的所有点之和
    缩点后的图是一个有向无环图(DAG)
    可拓扑排序,按照拓扑序进行DP
    子状态:(dp[i])表示以i结尾的路径的最大权值和
    状态转移方程 (dp[y]=max(dp[y],dp[x]+val[y]) ( (x,y) in E))
    最终的答案为max(dp[belong[u]]),其中u是酒吧编号,belong[u]表示酒吧所在的联通分量

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<map>
    #define maxn 500005
    using namespace std;
    struct edge{
    	int u;
    	int v;
    	edge(){
    		
    	}
    	edge(int from,int to){
    		u=from;
    		v=to;
    	}
    	friend bool operator < (edge a,edge b){
    		if(a.u==b.u) return a.v<b.v;
    		else return a.u<b.u;
    	}
    };
    map<edge,int>used;
    int n,m,st,p;
    vector<int>G[maxn];
    vector<int>D[maxn];
    int money[maxn];
    int tim=0;
    int cnt=0;
    int dfn[maxn];
    int low[maxn];
    int ins[maxn];
    int belong[maxn];
    long long dp[maxn],val[maxn];
    stack<int>s;
    void tarjan(int x){
    	s.push(x);
    	ins[x]=1;
    	dfn[x]=low[x]=++tim;
    	int t=G[x].size();
    	for(int i=0;i<t;i++){
    		int y=G[x][i];
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}else if(ins[y]){
    			low[x]=min(low[x],dfn[y]);
    		}
    	}
    	if(low[x]==dfn[x]){
    		cnt++;
    		int y;
    		do{
    			y=s.top();
    			s.pop();
    			ins[y]=0;
    			val[cnt]+=money[y];
    			belong[y]=cnt;
    		}while(x!=y);
    	}
    }
    
    int in[maxn];
    int out[maxn];
    void graph_to_dag(){
    	for(int i=1;i<=n;i++){
    		if(!dfn[i]) tarjan(i);
    	}
    	for(int i=1;i<=n;i++){
    		int t=G[i].size();
    		for(int j=0;j<t;j++){
    			int k=G[i][j];
    			if(belong[i]!=belong[k]){
    				if(used.count(edge(belong[i],belong[k]))) continue; 
    				used[edge(belong[i],belong[k])]=1;
    				D[belong[i]].push_back(belong[k]);
    				in[belong[k]]++;
    			}
    		}
    	}
    }
    
    int is_ok[maxn];
    void topo_sort(int s){
    	queue<int>q;
    	is_ok[s]=1;
    	for(int i=1;i<=cnt;i++){
    		if(in[i]==0){
    			q.push(i);
    		}
    	}
    	dp[s]=val[s];
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		int t=D[x].size();
    		for(int i=0;i<t;i++){
    			int y=D[x][i];
    			in[y]--;
    			if(is_ok[x]){
    				dp[y]=max(dp[y],dp[x]+val[y]);
    				is_ok[y]=1;
    			}
    			if(in[y]==0) q.push(y); 
    		}
    	}
    }
    
    int main(){
    	int u,v;
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%d %d",&u,&v);
    		G[u].push_back(v);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%d",&money[i]);
    	}
    	graph_to_dag();
    	scanf("%d %d",&st,&p);
    	topo_sort(belong[st]);
    	long long ans=0;
    	for(int i=1;i<=p;i++){
    		scanf("%d",&u);
    		ans=max(ans,dp[belong[u]]);
    	}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    有趣的网站
    Python-Day2
    C# EF增删改查
    LINQ教程
    命名空间“System.Web”中不存在类型或命名空间名称“Optimization”(是否缺少程序集引用?)
    Log4Net组件的应用详解
    log4net应用
    Select count(*)和Count(1)的区别和执行方式
    Ms sql 2005 中的bit 数据类型
    关于CLR、CIL、CTS、CLS、CLI、BCL和FCL
  • 原文地址:https://www.cnblogs.com/birchtree/p/9894105.html
Copyright © 2011-2022 走看看