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

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 
#include 
#include 
#include 
#include 
#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[N];
bool cmp(Edge x,Edge y)
{
    return x.rint 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;
}

你可能感兴趣的:(线段覆盖,仙人掌)