zoukankan      html  css  js  c++  java
  • bzoj 2657 旅游

    Written with StackEdit.

    Description

    到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~

    经过一番抉择,两人决定将(T)国作为他们的目的地。(T)国的国土可以用一个凸(N)边形来表示,(N)个顶点表示(N)个入境/出境口。T国包含(N-2)个城市,每个城市都是顶点均为(N)边形顶点的三角形(换而言之,城市组成了关于(T)国的一个三角剖分)。两人的旅游路线可以看做是连接(N)个顶点中不相邻两点的线段。

    为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?

    Input

    每个输入文件中仅包含一个测试数据。

    第一行包含两个由空格隔开的正整数(N)(N)的含义如题目所述。

    接下来有(N-2)行,每行包含三个整数(p,q,r),表示该城市三角形的三个顶点的编号((T)国的(N)个顶点按顺时间方向从(1)(N)编号)。

    Output

    输出文件共包含(1)行,表示最多经过的城市数目。(一个城市被当做经过当且仅当其与线路有至少两个公共点)

    Sample Input

    6
    1 2 4
    2 3 4
    1 4 5
    1 5 6

    Sample Output

    4

    HINT

    (4<=N<=200000)

    Solution

    • 将每个三角形看成一个点.相邻的两个三角形之间连边.
    • 注意到三角剖分中,一定需要剖(N-3)次,每剖一次,图中多出一条边,这条边只能连接一对三角形.(节点).
    • 那么这个图共有(N-2)个点,(N-3)条边,且是连通的.
    • 那么所求的答案即为树的直径.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LoveLive;
    typedef pair<int,int> pii;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=2e5+10;
    map<pii,int> s;
    map<pii,int>::iterator it;
    int n;
    int cnt=0,head[MAXN];
    int nx[MAXN<<1],to[MAXN<<1];
    inline void add(int u,int v)
    {
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    }
    inline void ins(int u,int v)
    {
    	add(u,v);
    	add(v,u);
    }
    int dep[MAXN],q[4];
    void opr(int a,int b,int i)
    {
    	it=s.find(make_pair(q[a],q[b]));
    	if(it!=s.end())
    		ins(it->second,i),s.erase(it);
    	else
    		s[make_pair(q[a],q[b])]=i;
    }
    void dfs(int u,int fa)
    {
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			if(v==fa)
    				continue;
    			dep[v]=dep[u]+1;
    			dfs(v,u);
    		}
    }
    int getd()
    {
    	int res=-1,rt;
    	dep[1]=1;
    	dfs(1,0);
    	for(int i=1;i<=n-2;++i)
    		if(dep[i]>res)
    			res=dep[i],rt=i;
    	dep[rt]=1;
    	dfs(rt,0);
    	for(int i=1;i<=n;++i)
    		res=max(res,dep[i]);
    	return res;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n-2;++i)
    		{
    			q[1]=read();
    			q[2]=read();
    			q[3]=read();
    			sort(q+1,q+4);
    			opr(1,2,i);
    			opr(1,3,i);
    			opr(2,3,i);
    		}
    	int ans=getd();
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    因为这几个TypeScript代码的坏习惯,同事被罚了500块
    如何设计好分布式数据库,这个策略很重要
    线程、多线程和线程池,看完这些你就能全部搞懂了
    章方:征服耶鲁教授的算法大神程序媛
    从零开始学python | 使用Python映射,过滤和缩减函数:所有您需要知道的
    c# 优化代码的一些规则——用委托表示回调[五]
    mysql 重新整理——索引优化explain字段介绍一 [九]
    mysql 重新整理——索引优化explain简单介绍 [八]
    mysql 重新整理——索引简介[七]
    mysql 重新整理——七种连接join连接[六]
  • 原文地址:https://www.cnblogs.com/jklover/p/10054182.html
Copyright © 2011-2022 走看看