BZOJ 1977 次小生成樹(最近公共祖先)

2022-05-09 01:57:08 字數 1649 閱讀 4283

題意:求一棵樹的嚴格次小生成樹,即權值嚴格大於最小生成樹且權值最小的生成樹。

先求最小生成樹,對於每個不在樹中的邊,取兩點間路徑的資訊,如果這條邊的權值等於路徑中的權值最大值,那就刪掉路徑中的次大值,加上這條非樹邊,更新答案;否則刪掉路徑中的最大值,加上這條非樹邊,更新答案。

1 #include2 #include3 #include4 #include5 #include6

#define ll long long

7struct

edgee[300005

];11

int tot,go[600005],first[300005],next[600005

];12 ll val[600005

];13

int fa[100005][18],deep[100005],f[100005],bin[105

],n,m;

14 ll mx1[100005][18],mx2[100005][18

],ans1,ans2;

15int

read()

18while ('0'

<=ch&&ch<='9')

19return t*f;20}

21ll read()

24while ('0'

<=ch&&ch<='9')

25return t*f;26}

27bool

cmp(edge a,edge b)

30void insert(int x,int

y,ll z)

37void add(int x,int y,int

z)40

int find(int

x)44

void up(ll x,ll &y)

47void work(int x,int

i)54

void dfs(int x,int

f) 66}67

void up(ll x,ll &a,ll &b)

72void lca(int x,int

y)82

for (int i=17;i>=0;i--)

83if (fa[x][i]!=fa[y][i])

91if (x!=y)97}

98int

main()

108for (int i=1;i<=n;i++)

109for (int j=0;j<=17;j++)

110 mx1[i][j]=mx2[i][j]=0

;111 std::sort(e+1,e+1+m,cmp);

112 ll sum=0

;113

for (int i=1;i<=n;i++) f[i]=i;

114for (int i=1;i<=m;i++)

115if (find(e[i].u)!=find(e[i].v))

121 dfs(1,0

);122 ll ans=10000000000000000ll;

123for (int i=1;i<=m;i++)

124if (!e[i].id)

129 printf("

%lld\n

",ans);

130 }

BZOJ 1977 次小生成樹

傳送門 求嚴格次小生成樹 權值和嚴格小於最小生成樹 和無限制的次小生成樹一樣,唯一不同的是,嚴格小於,只需要將刪除非樹邊連線的兩點樹鏈上的最長邊改為刪除1.如果最長邊不等於該邊,就直接計算2.如果等於,就用次長邊計算。在最小生成樹上倍增即可。includeusing namespace std na...

BZOJ 1977 次小生成樹(最近公共祖先)

題意 求一棵樹的嚴格次小生成樹,即權值嚴格大於最小生成樹且權值最小的生成樹。思路 若現在已經得到了最小生成樹,那麼若 新增一條邊e,就會得到乙個環,我們只需要去掉環上權值小於e且最大的一條邊就會得到另一棵較優的生成樹。因此,只需要列舉不在生成樹上的邊,計算將其添 加到最小生成樹中得到的新生成樹的權值...

BZOJ 1977 嚴格次小生成樹

題目鏈結 題意 求乙個圖的嚴格次小生成樹,n 100000,m 300000,邊權非負且 1e9 思路 按照正常次小生成樹思路,先生成一顆最小生成樹,並記錄任意兩點路徑上的最長邊,然後列舉非最小樹邊來求得答案,但現在要求的是嚴格次小生成樹所以我們還得知道兩點路徑上的嚴格次長邊 我們考慮使用lca維護...