2017.9.2 最大半联通子图 思考记录

这个题一看上去似乎很难,,   半联通子图根本就没听说过啊

但经过一段时间的思考之后似乎模型挺直接的、

但是其实,他就是问你一个选点最多的路径、 因为如果这些点如果不能能构成一条路径的话,不在路径上的点一定会以一个方向走入这条路径来 会导致相反方向的点不能到达



对于能互达的点,他们发出的任意一条边都可以作为路径,因此tarjan缩点  然后用拓扑序找路径即可

2A(第一遍MLE、)

码:


#include
#include
using namespace std;
#include
#include
#include
vectorv[100005];
queueq;
#define N 1000005
int dis,hou[N],xia[N],zhong[N],qi[N],d[N],s[N],sta[N],top,tot,cnt,jh[N],ru[N],f[N][3],pd[N],n,m,x,max1,max2;
void jian(int x,int y)
{
	++tot;hou[tot]=xia[x];xia[x]=tot;zhong[tot]=y;qi[tot]=x;	
}
void dfs(int o)
{
	int i;
	d[o]=++dis;
	s[o]=dis;
	sta[++top]=o;	
	for(i=xia[o];i!=-1;i=hou[i])
	{
		int nd=zhong[i];
		//if(nd==fu)continue;
		if(d[nd]==0)
		{			
			  dfs(nd);s[o]=min(s[o],s[nd]);
		}else if(jh[nd]==0)s[o]=min(s[o],s[nd]);		
	}
	if(s[o]==d[o])
	{    ++cnt;
		while(sta[top]!=o)
		{
		jh[sta[top]]=cnt;
		v[cnt].push_back(sta[top]);
		top--;		
		}	
		jh[sta[top]]=cnt;
		v[cnt].push_back(sta[top]);
		top--;		
	}	
}
void dp()
{
	int i,j;
	for(i=1;i<=m;i++)
	{
		if(jh[qi[i]]!=jh[zhong[i]])ru[jh[zhong[i]]]++;		
	}
	for(i=1;i<=cnt;i++)
	{
		if(ru[i]==0)q.push(i);
	}
	while(!q.empty())
	{
		int st=q.front();
		f[st][0]+=v[st].size();
		if(f[st][1]==0)f[st][1]=1;
		q.pop();
		for(i=0;i






你可能感兴趣的:(题目)