vector<int> v[N];
vector<pair<int,int> > e[N];
void add_edge(int a,int b){
v[a].eb(b);
}
void add_edge(int a,int b,int w) {
e[a].eb(mp(b,w));
}void dfs(int x){
vis[x]=true;
for(int i:v[x]){
if(!vis[i]) dfs(i);
}
}void bfs(int s){
queue<int> q;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
for(int i:v[x]) {
if(!vis[i]){
vis[i]=true;
q.push(i);
}
}
}
}wiwihorz 讀書會圖論I簡報的 code
wiwihorz 讀書會圖論I簡報的 code
void dfs(int x){
for(int &p=it[x];p<SZ(e[x]);p++){
if(!used[e[x][p].S]) {
used[e[x][p].S]=1;
dfs(e[x][p].F);
}
}
ans.eb(x);
}void dfs(int x,int p=-1,int d=0){
dep[x]=d;
for(int i:v[x]){
if(i==p) continue;
dfs(i,x,d+1);
}
}int dis[N],maxdep[x];
void dfs(int x,int p=-1){
maxdep[x]=dis[x]=0;
for(int i:v[x]){
if(i!=p){
dfs(i,x);
dis[x]=max(dis[x],max(dis[i],maxdep[x]+maxdep[i]+1));
maxdep[x]=max(maxdep[x],maxdep[i]+1);
}
}
}void toplogical sort(){
queue<int> q;
for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
while(q.size()){
int x=q.front();
q.pop();
for(auto [i,w]:v[x]){
deg[i]--;
if(!deg[i]) q.push(i);
}
}
}每個任務 \(x\) 有其花費天數、也有一些順序關係。他能開始做只有當連向 \(x\) 的所有任務都完成了
void toplogical sort(){
queue<int> q;
for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
while(q.size()){
int x=q.front();
q.pop();
for(auto [i,w]:v[x]){
dp[i]=max(dp[i],dp[x]+w);
deg[i]--;
if(!deg[i]) q.push(i);
}
}
}一種資料結構可以進行兩種操作
void init(int n){
for(int i=1;i<=n;i++) p[i]=i,sz[i]=1;
}
int fp(int x){
if(x!=p[x]) p[x]=fp(p[x]);//路徑壓縮
return p[x];
}
void Union(int a,int b){
a=fp(a);//找到連通塊的祖先
b=fp(b);
if(a!=b){
if(sz[a]<sz[b]){
swap(a,b);//確保a是數量較大的
}
p[b]=a;//把b指向a
sz[a]+=sz[b];
}
}
int in[N],out[N];
int t=1;
void dfs(int x,int p=-1){
in[x]=t++; // 進入的時間戳記
for(int i:v[x]) {
if(i!=p) dfs(i,x);
}
out[x]=t++; // 離開的時間戳記
}bool isanc(int a,int b){
return in[a]<=in[b]&&out[b]<=out[a];
}void build(){
for(int i=1;i<=K;i++){
for(int j=1;j<=n;j++) ac[i][j]=ac[i-1][ac[i-1][j]];
}
}int LCA(int a,int b){
if(isanc(a,b)) return a;
if(isanc(b,a)) return b;
for(int i=K;i>=0;i--){//跳到洽 $k_1-1$ 層的位置
if(!isanc(ac[i][a],b)) a=ac[i][a];
}
return ac[0][a];
}int in[N],out[N];
int t=1;
void dfs(int x,int p=-1){
in[x]=t++; // 進入的時間戳記
if(p!=-1) ac[0][x]=p;
else ac[0][x]=x; // 預處理父親
for(int i:v[x]) {
if(i!=p) dfs(i,x);
}
out[x]=t++; // 離開的時間戳記
}
void build(){
for(int i=1;i<=K;i++){
for(int j=1;j<=n;j++) ac[i][j]=ac[i-1][ac[i-1][j]];
}
}
bool isanc(int a,int b){//判斷 a 是否為 b 的祖先
return in[a]<=in[b]&&out[b]<=out[a];
}
int LCA(int a,int b){
if(isanc(a,b)) return a;
if(isanc(b,a)) return b;
for(int i=K;i>=0;i--){//跳到洽 $k_1-1$ 層的位置
if(!isanc(ac[i][a],b)) a=ac[i][a];
}
return ac[0][a];
}同時也會是權重最大值最小的樹
DSU s; //並查集
void Kruskal(vector<edge> e){
sort(e.begin(),e.end(),cmp);//按照邊權由小到大排
int sum=0;
for(edge ei:e){
if(!s.same(ei.a,ei.b)) s.union(ei.a,ei.b),sum+=ei.w;
}
}typedef pair<int,int> pii;
void dijkistra(int s,int t){
priority_queue<pii,vector<pii>,greater<pii>> pq;
pq.push(mp(0,s));
fill(dis,dis+N,INF);
dis[s]=0;
while(pq.size()){
pii now=pq.top();
pq.pop();
for(pii p2:v[now.S]){
if(dis[p2.F]>dis[now.S]+p2.S) {
dis[p2.F]=dis[now.S]+p2.S;
pq.push(mp(dis[p2.F],p2.F));
}
}
}
}typedef pair<int,int> pii;
void dijkistra(int s,int t){
priority_queue<pii,vector<pii>,greater<pii>> pq;
pq.push(mp(0,s));
fill(dis,dis+N,INF);
dis[s]=0;
while(pq.size()){
pii now=pq.top();
pq.pop();
if(dis[now.S]<now.F) continue; //允許重複入隊寫法
for(pii p2:v[now.S]){
if(dis[p2.F]>dis[now.S]+p2.S) {
dis[p2.F]=dis[now.S]+p2.S;
pq.push(mp(dis[p2.F],p2.F));
}
}
}
}wiwihorz 暑培圖論II簡報的 code
wiwihorz 暑培圖論II簡報的 code
wiwihorz 暑培圖論II簡報的 code
void FloydWarshall(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dis[i][j]=min(dis[i][k]+dis[k][j]);
}
}
}
}