您的位置:首页 > 其它

【NOIP2014八校联考第1场第1试9.20】简单题

2018-02-06 22:39 344 查看
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。

The Solution

我们把 1 到 n 的这条链看作是一条线段。再加边看作是用一条新的线段来覆盖。根据仙人掌图的定义,任何一条边不能同时存在于两个不同的环中。意思就是在新加的这些线段中不能有任何两条线段覆盖同一个区域。求最多的边就是求最多的线段。

CODE

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define INF 1 << 30
#define mo 10086
#define N 100005

using namespace std;

struct Edge
{
int l,r;
}a[N * 2];

int n,m;
bool Flag
;
bool cmp(Edge x,Edge y)
{
return x.r<y.r;
}

int read(int &n)
{
char ch = ' ';
int q = 0, w = 1;
for (;(ch != '-') && ((ch < '0') || (ch> '9'));ch = getchar());
if (ch == '-') w = -1,ch = getchar();
for (; ch >= '0' && ch <= '9';ch = getchar()) q = q * 10 + ch - 48;
n = q * w;
return n;
}

namespace ib {char b[100];}

inline void pint(int x)
{
if (x == 0)
{
putchar(48);
return;
}
if (x < 0)
{
putchar('-');
x = -x;
}
char *s = ib :: b;
while (x) *(++ s) = x % 10,x /= 10;
while (s != ib :: b) putchar((* (s --)) + 48);
}

int main()
{
read(n),read(m);
fo(i,1,m)
{
int x,y;
read(x),read(y);
if (x > y) swap(x,y);
a[i].l = x,a[i].r = y;
}
sort(a+1,a+1+m,cmp);
int x = 1,ans = n - 1;
fo(i,1,m)
{
if (a[i].r == a[i].l + 1 && !Flag[a[i].l])
{
Flag[a[i].l] = true;
continue;
}
if (a[i].l < x) continue;
x = a[i].r;
ans ++;
}
pint(ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段覆盖