POJ--3567[Cactus Reloaded] 求仙人掌树的直径

 

题目大意:

给一棵仙人掌(就是所有的边都在至多一个环中的图),求仙人掌的直径,也就是最短路径最长的一对点的最短路径。

思路:

 

/*无向图的连通性*/
/*
思路:
(1):一遍dfs,遇到割点执行Judge()
(2):遇到割点时栈(存边)里面的图形只可能是1.长度为1的线段;2.一个圆环。
(3):缩点之前还要对W[u]大于1的那些点进行两两组合更新答案
*/

 

PS.

Discuss里说要用树形DP+单调队列优化,表示这两个都不太会,结果就暴力了点,发现也能过、

 

CODE:

 

/*AC代码:1188ms*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#include <algorithm>
#include <stack>
#include <time.h>
#include <cmath>
#include <cstdlib>
#define MAXN 50005
#define INF 1e8
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
struct Node
{
	int w,p;
}node[MAXN];
int vcnt;
struct edge
{
	int u,v,id,next;
}E[500000];
int head[MAXN],ecnt;
int low[MAXN],dfn[MAXN],col[MAXN],dis[MAXN];
int W[MAXN];//每个点的权值
int t[MAXN];
bool vis[MAXN];
int N,M,Index,ans,root;
void Insert(int u,int v)
{
	E[ecnt].u=u;
	E[ecnt].v=v;
	E[ecnt].id=ecnt;
	E[ecnt].next=head[u];
	head[u]=ecnt++;
}
void Init()
{
	int i,j,u,v,w;
	memset(head,-1,sizeof(head));ecnt=0;
	for(i=1;i<=M;i++)
	{
		scanf("%d",&w);
		scanf("%d",&u);
		for(j=2;j<=w;j++)
		{
			scanf("%d",&v);
			Insert(u,v);
			Insert(v,u);
			u=v;
		}
	}
	/*
	for(i=0;i<ecnt;i+=2)
	printf("*%d %d\n",E[i].u,E[i].v);
	*/
}
int cmp(const void *p1,const void *p2)
{
	return ((struct Node *)p2)->w-((struct Node *)p1)->w;
}
stack<int>_S;
void Run(int n)
{
	int i,j,p1,p2;
	for(i=0;i<vcnt;i++)
	{
		p1=node[i].p;
		int res=0;
		for(j=i+1;j<vcnt;j++)
		{
			p2=node[j].p;
			res=max(res,min(abs(p2-p1),n-abs(p2-p1))+node[j].w);
		}
		ans=max(ans,res+node[i].w);
	}
	qsort(node,vcnt,sizeof(node[0]),cmp);
	ans=max(ans,node[0].w+n/2);
}
void Judge(int t[],int num,int now)
{
	int i,v,res=0;
	vcnt=0;
	for(i=0;i<num-1;i++)
	{
		v=t[i];
		if(W[v])
		{node[vcnt].w=W[v];node[vcnt++].p=i;}
		res=max(res,min(num-1-i,i+1)+W[v]);
	}
	ans=max(ans,W[now]+res);//跟新答案
	W[now]=max(W[now],res);//更新节点
	Run(num);
}
void dfs(int now,int father)
{
	//printf("*%d\n",now);
	int i,v,x;
	col[now]=1;
	low[now]=dfn[now]=++Index;
	for(i=head[now];i!=-1;i=E[i].next)
	{
		v=E[i].v;
		if(v!=father&&col[v]==1)//反向边
		{
			_S.push(E[i].id);
			low[now]=min(low[now],dfn[v]);
		}
		if(col[v]==0)//树边
		{
			_S.push(E[i].id);
			dfs(v,now);
			low[now]=min(low[now],low[v]);
			if(dfn[now]<=low[v])
			{
				int num=0;
				x=_S.top();_S.pop();
				if(E[x].v!=now)
				{
					t[num++]=E[x].v;
					t[num++]=E[x].u;
					Judge(t,num,now);
				}
				else
				{
					t[num++]=E[x].u;
					while(1)
					{
						x=_S.top();_S.pop();
						t[num++]=E[x].u;
						if(t[num-1]==now) break;
					}
					Judge(t,num,now);
				}
				//printf("--%d %d\n",now,W[now]);
			}
		}
	}
	col[now]=2; 
}
void Solve()
{
	Index=0;
	memset(col,0,sizeof(col));
	memset(dfn,0,sizeof(dfn));
	memset(W,0,sizeof(W));
	while(!_S.empty()) _S.pop();
	ans=0;
	dfs(1,1);
	printf("%d\n",ans);
}
int main()
{
	//freopen("50.in","r",stdin);
	//freopen("c.txt","w",stdout);
	while(scanf("%d%d",&N,&M)!=EOF)
	{
		Init();
		Solve();
	}
	return 0;
}

/*
12 5
7 1 2 3 4 5 6 7
2 4 6
2 3 8
5 2 8 9 10 11
3 9 12 10

ans=7;
  
7 1
8 7 6 5 4 3 2 1 6

ans=4;
*/


 

 

你可能感兴趣的:(优化,struct,insert,图形)