並查集 codevs 1188City戰爭

2021-08-02 07:06:23 字數 1656 閱讀 5827

我靠我不會;

fop_zz教我了半天我才會的;

首先n*n的暴力就是每條線段從兩個點dfs;

然後把兩個點的值乘起來*2;

這就是一條的值了;

我們在考慮權值不同的情況;

我們只要把邊從小到大排序然後用並查集維護就好了;

但是如果邊權有相同的情況就不好搞了;

有乙個想法;

就是我們同乙個權值的邊一起加;

對於一條邊,加之前其一段的點數是a,加之後是總共點數b;

那麼值就是(b-a)*a*2;

這就有問題了,我們並查集不可以存點數了;

因為並查集在不斷變化;

那我們只好把點數存在點上了;

這個時候我們要先搞乙個dfs樹;

記錄每個節點的深度;

而並查集維護的就是這個聯通快的點數放在**;

其實全放在聯通快深度最高點;

我們合併兩個並查集的時候,就要把低節點合併到高節點去;

比如x-y這一線段

x深度淺

那麼get(y)一定是y

我們要把

fa[y]=get(x)

並且把點數合併過去;

於是y~get(x)的點的點數全要加x的點數;

因為我們要計算答案的;

僅僅把get(x)的權值加上y是不夠的;

#include

#define ll long long

using namespace std;

const

int n=1e5+5;

struct csa[n*2];

struct

ini[n];

struct diand[n];

int fa[n];

int head[n],ll;

int an[n],top;

ll ans;

int n,m,l,r,x,y,z;

void init(int x,int y,int z)

void dfs(int x,int y,int z)

bool cmp(in a,in b)

void insert(int x,int y)

int main()

dfs(1,-1,1);

sort(i+1,i+n+1,cmp);

l=1;r=1;

while(l<=n)

for(int i=l;i<=r;i++)else

ll temp=(ll)(y-x)*x;

if(ans==temp)an[++top]=i[i].num;

if(ans1]=i[i].num;

}l=r+1;r=l;

}sort(an+1,an+top+1);

printf("%lld %d\n",ans*2,top);

for(int i=1;i<=top;i++)printf("%d ",an[i]);

}

其實這種寫法會被卡掉;

我們搞一條鏈的話

for(int k=d[x].fa;k!=yy;k=d[k].fa)d[k].size+=d[x].size;
這裡會萎;

但是如果我們把同權值的線段先排序;

這就好啦

並查集之團夥(codevs)

時間限制 1 s 空間限制 128000 kb 1920年的芝加哥,出現了一群強盜。如果兩個強盜遇上了,那麼他們要麼是朋友,要麼是敵人。而且有一點是肯定的,就是 我朋友的朋友是我的朋友 我敵人的敵人也是我的朋友。兩個強盜是同一團夥的條件是當且僅當他們是朋友。現在給你一些關於強盜們的資訊,問你最多有多...

並查集 並查集

本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...

codevs 星際跳躍並查集的應用

題目描述 description 小 k 又在玩浴火銀河了。不過這次他的目的不是跑運輸賺錢,而 是做任務賺錢。他想知道關於乙個任務的兩個星系是否可以連通。輸入描述 input description 第一行,三個數,x,n,m x 表示出現的星系代號的最大值 n 表示有 n 個星際跳躍門 m 表示有...