• 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);
    }
    
  • 相关阅读:
    IP负载均衡技术
    ES6 克隆对象 浅克隆:只能克隆原始对象自身的值,不能克隆它继承的值
    多层nginx中的压缩问题 api接口>1M数据的返回浏览器 网关
    Status Code: 431 Request Header Fields Too Large
    研发过程中的测试工作
    dede文章页调用当前栏目链接方法
    dedecms做好的网站怎么上传到网上?
    如何修改"DEDECMS 提示信息!"方法!
    dedecms搜索提示"关键字不能小于2个字节!"
    修改cms版权等等信息
  • 原文地址:https://www.cnblogs.com/birchtree/p/9894105.html
Copyright © 2020-2023  润新知