JZOJ 3845. 简单题(simple)

题目

Description

dzy 手上有一张n 个点m 条边的联通无向图,仙人掌是一张每条边最多在一个简单环内的联通无向图。他想求这个无向图的生成仙人掌中最多有多少条边。
但是dzy 觉得这个问题太简单了,于是他定义了“美丽的生成仙人掌”,即在一个生成仙人掌中如果满足对于任意编号为i,j(i < j) 的两点,存在一条它们之间的简单路径上面有j-i+1 个点,则这个仙人掌是美丽的。
他现在想要知道这张图的美丽的生成仙人掌中最多有多少条边,你能帮帮他吗?
 

Input

第一行两个整数n,m。接下来m 行每行两个整数ui,vi,表示这两个点之间有一条无向边。保证图中没有自环。

Output

仅一行一个整数表示答案。
 

Sample Input

2 1
1 2

Sample Output

1
 

Data Constraint

对于10% 的数据,n <=10。
对于30% 的数据,n <=10^3。
对于100% 的数据,n <=10^5,m <= 2n。

 

分析

 

  • 我们易得美丽仙人掌一定是一条链 并且上面很多的环
  • 对于一条边 我们需要纪录几个信息
  • x+1==y 如果不是那么他的环指向哪里
  • 然后我们枚举每个点作为起点
  • 找一条链 每次往里面找环每次把环变得尽量小

代码

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #define ll long long
 7 using namespace std;
 8 int last[100010],nxt[100010];
 9 struct sb
10 {
11     int x,y;
12 }a[100010];
13 bool cmp(sb a,sb b){return a.x<b.x;}
14 int main()
15 {
16     int n,m;
17     scanf("%d%d",&n,&m);
18     memset(last,0x7f,sizeof(last)) ;
19     for (int i=1,x,y;i<=m;i++)
20     {
21         scanf("%d%d",&x,&y);
22         if (x>y) swap(x,y);
23         if (y==x+1&&nxt[x]==1) last[x]=y;
24         if (y==x+1) nxt[x]=1;
25         if (y<last[x]&&y!=x+1) last[x]=y;
26     }
27     int ans=0;
28     for (int i=1;i<=n;i++)
29     {
30         int j=i,cnt=0,x=i,tot=0,l=0;
31         for (;nxt[j];j++)
32         {
33             a[++tot].x=last[j];
34             a[tot].y=j;
35         }
36         sort(a+1,a+1+tot,cmp);
37         for (int k=1;k<=tot;k++)
38         {
39             if (a[k].y>=l&&a[k].x<=999999999)
40             {
41                 l=a[k].x;
42                 cnt++;
43             }
44         }
45         ans=max(ans,j-i+cnt);
46         i=j;
47     }
48     cout<<ans;
49     return 0;
50 }
原文地址:https://www.cnblogs.com/zjzjzj/p/11806262.html