zoukankan      html  css  js  c++  java
  • 【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu

    有向图,不经过重复点的最长链,强连通分量大小不超过5。

    每个强连通分量内部暴力预处理任意两对点之间的最长路,外面DAG上dp。

    不是很好写,但是预处理完了之后,可以重构每个强连通分量内部的结构,然后整个就变成一张DAG了,就很方便了。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define MAX_V 200005
    using namespace std;
    int n,ans,ans1[MAX_V],ans2[MAX_V],c[MAX_V][6],cnum[MAX_V],id[MAX_V],dis[MAX_V][6],m;
    vector<int> G[MAX_V];
    vector<int> rG[MAX_V];
    vector<int> vs;
    bool used[MAX_V];
    int cmp[MAX_V];
    void add_edge(int from,int to)
    {
    	G[from].push_back(to);
    	rG[to].push_back(from);
    }
    void dfs(int v)
    {
    	used[v]=1;
    	for(int i=0;i<G[v].size();++i)
    	{
    		if(!used[G[v][i]])
    			dfs(G[v][i]);
    	}
    	vs.push_back(v);
    }
    void rdfs(int v,int k)
    {
    	used[v]=1;
    	cmp[v]=k;
    	for(int i=0;i<rG[v].size();++i)
    	{
    		if(!used[rG[v][i]])
    		rdfs(rG[v][i],k);
    	}
    }
    int scc()
    {
    	memset(used,0,sizeof used);
    	vs.clear();
    	for(int v=1;v<=n;v++)
    	{
    		if(!used[v]) dfs(v);
    	}
    	memset(used,0,sizeof used);
    	int k=1;
    	for(int i=vs.size()-1;i>=0;--i)
    	{
    		if(!used[vs[i]]) 
    		rdfs(vs[i],k++);
    	}
    	return k;
    }
    void cal(int now,int nowid,int f,int nowdis)
    {
    	used[now]=1;
    	dis[now][nowid]=max(dis[now][nowid],nowdis);
    	for(int i=0;i<G[now].size();++i)
    	if(cmp[G[now][i]]==f&&!used[G[now][i]])
    	{
    		cal(G[now][i],nowid,f,nowdis+1);
    	}
    	used[now]=0;
    	return;
    }
    int get2(int now);
    int get1(int now)
    {
    	if(ans1[now]!=-1) return ans1[now];
    	int nowans=1;
    	for(int i=0;i<rG[now].size();i++)
    	if(cmp[rG[now][i]]!=cmp[now])
    	{
    		nowans=max(nowans,get2(rG[now][i])+1);
    	}
    	return ans1[now]=nowans;
    }
    int get2(int now)
    {
    	if(ans2[now]!=-1) return ans2[now];
    	int nowans=-1;
    	for(int i=1;i<=cnum[cmp[now]];++i)
    	{
    		nowans=max(nowans,get1(c[cmp[now]][i])+dis[now][i]);
    	}
    	return ans2[now]=nowans;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int u,v;
    	for(int i=1;i<=m;++i)
    	{
    		scanf("%d%d",&u,&v);
    		add_edge(u,v);
    	}
    	scc();
    	memset(used,0,sizeof used);
    	for(int i=1;i<=n;++i)
    	{
    		ans1[i]=ans2[i]=-1;
    		c[cmp[i]][++cnum[cmp[i]]]=i;
    		id[i]=cnum[cmp[i]];
    		cal(i,id[i],cmp[i],0);
    	}
    	for(int i=1;i<=n;++i)
    	{
    		ans=max(ans,get2(i));
    	}
    	cout<<ans;
    	return 0;
    }
  • 相关阅读:
    用户代理检测浏览器、引擎、平台、设备、游戏系统
    浏览器检测
    js 实现table每列可左右拖动改变列宽度 【转载】
    检测flash是否安装及版本号
    高亮显示搜索的关键词(二)
    修改鼠标选中文本的样式
    高亮显示搜索的关键词
    让站长在SEO时更得心应手的六个细节
    JQuery图片延迟加载插件,动态获取图片长宽尺寸
    jquery 图片背景透明度(支持IE5/IE6/IE7)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7198319.html
Copyright © 2011-2022 走看看