我靠我不會;
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 表示有...