1. 程式人生 > >仙人掌(cactus)

仙人掌(cactus)

輸出格式 出發 個數 define color using ... 分享 return

題目描述
LYK 在沖刺清華集訓(THUSC)!於是它開始研究仙人掌?,它想來和你一起分享它最近
研究的結果。
如果在一個無向連通圖中任意一條邊至多屬於一個簡單環(簡單環的定義為每個點至多
經過一次),且不存在自環,我們稱這個圖為仙人掌。
LYK 覺得仙人掌還是太簡單了,於是它定義了屬於自己的仙人掌。
定義一張圖為美妙的仙人掌,當且僅當這張圖是一個仙人掌且對於任意兩個不同的點 i,j,
存在一條從 i 出發到 j 的路徑,且經過的點的個數為|j-i|+1 個。
給定一張 n 個點 m 條邊且沒有自環的圖,LYK 想知道美妙的仙人掌最多有多少條邊。
數據保證整張圖至少存在一個美妙的仙人掌。
輸入格式(cactus.in)
第一行兩個數 n,m 表示這張圖的點數和邊數。
接下來 m 行,每行兩個數 u,v 表示存在一條連接 u,v 的無向邊。
輸出格式(cactus.out)
一個數表示答案
輸入樣例
4 6
1 2
1 3
1 4
2 3
2 4
3 4
輸出樣例
4

思路:

  題目保證一定存在i到i+1的邊。那我就不去處理了。(保證一定存在 1,——2——3——4......n-1——n。這樣的鏈。)

  只要處理 在 1,——2——3——4......n-1——n。這條鏈上,加上盡可能多的邊,不會出現某一個邊被包含在多個環中。

  咦!這不就轉化成了區間覆蓋問題了!

dp貪心兩種寫法。

dp

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define MAXN 100010
int
f[MAXN],g[MAXN]; int n,m; int main() { freopen("cactus.in","r",stdin); freopen("cactus.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1,u,v;i<=m;i++) { scanf("%d%d",&u,&v); if(u>v) swap(u,v); if(u+1!=v) g[v]=max(g[v],u); } f[
0]=-1; for(int i=2;i<=n;i++) f[i]=max(f[i-1],f[g[i]]+1); printf("%d",f[n]+n-1); return 0; }

貪心

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
int n,m;
struct node
{
    int x,y;
};node e[N*2];
bool cmp(const node&s1,const node&s2)
{
    return s1.y<s2.y;
}
int main()
{
    //freopen("cactus.in","r",stdin);
    //freopen("cactus.out","w",stdout);
    scanf("%d%d",&n,&m);
    int t=0;
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        if(x>y)swap(x,y);
        if(x+1!=y)e[++t].x=x,e[t].y=y;
    }
    sort(e+1,e+t+1,cmp);
    int tot=0,p=0;
    for(int i=1;i<=t;i++)
      if(e[i].x>=p)p=e[i].y,tot++;
    printf("%d",tot+n-1);
    return 0;
}

仙人掌(cactus)