目錄
並查集
int fa[MAX];
void init(){
for(int i=0;i<MAX;i++)fa[i]=i;
}
int find(int i){
int temp=i;
while(temp!=fa[temp])temp=fa[temp];
if(temp!=i){
int t=fa[i];
fa[i]=temp;
i=t;
}
return temp;
}
void merge(int a,int b){
fa[a]=b;
}
最小生成樹(克魯斯卡爾)
struct edge {
int u,v,w;
};
int n,m,a,b,c;
vector<edge> v;
bool cmp(edge a,edge b) {
return a.w<b.w;
}
int kruskal(){
init(); // 初始化並查集
int ans=0;
sort(v.begin(),v.end(),cmp); // 按照邊權值的大小排序
for(int i=0; i<v.size(); i++) { // 依次選擇權值小的邊
int a=find(v[i].u);
int b=find(v[i].v);
if(a!=b) { // 判斷這兩個點是否已經連接
merge(a,b);
ans+=v[i].w;
}
}
return ans;
}
最短路(Dijkstra)
int vis[MAX],d[MAX];
int w[MAX][MAX];
// 以鄰接矩陣存儲圖
void dijkstra(){
memset(vis,0,sizeof(vis)); // 初始化vis數組
for(int i=1;i<=n;i++)d[i]=w[1][i]; // 初始化到起點的距離
vis[1]=1;
for(int i=1;i<=n;i++){
int minn=INF,k=0;
for(int j=1;j<=n;j++) // 尋找當前路徑最短的點
if(!vis[j] && d[j]<minn)
minn=d[j],k=j;
vis[k]=1;
for(int j=1;j<=n;j++) // 鬆弛操作
if(!vis[j] && minn+w[k][j]<d[j])d[j]=minn+w[k][j];
}
}
最短路(SPFA)
struct node { // 連接的點和到達該點的時間
int to,time;
};
vector<node> G[MAX];
int n,m,a,b,c;
int vis[MAX],d[MAX];
// 以鄰接表存儲圖
void spfa() {
memset(vis,0,sizeof(vis)); // 初始化vis數組
for(int i=0; i<MAX; i++) d[i]=INF; // 初始化距離最大
queue<node> q;
q.push({1,0}); // 起點入列
vis[1]=1; // 進入隊列標誌
d[1]=0; // 起點距離爲0
while(!q.empty()) {
node u=q.front(); q.pop();
vis[u.to]=0; // 出隊列標誌
for(int i=0; i<G[u.to].size(); i++) { // 遍歷所有鄰接的點
node v=G[u.to][i];
if(d[v.to]>d[u.to]+v.time) { // 鬆弛操作
d[v.to]=d[u.to]+v.time;
if(!vis[v.to]) { // 如果沒有入列則入列
vis[v.to]=1;
q.push(v);
}
}
}
}
}
最短路(Floyd)
int w[MAX][MAX];
// 以鄰接矩陣存儲圖
void floyd(){
for(int k=1;k<=n;k++){ // 作爲中間節點
for(int i=1;i<=n;i++){
if(w[i][k]!=INF){
for(int j=1;j<=n;j++){
w[i][j]=min(w[i][j],w[i][k]+w[k][j]); // 鬆弛操作
}
}
}
}
}
拓撲排序
int w[MAX][MAX];
int rd[MAX]; // 存儲結點的入度
int vis[MAX];
int topo[MAX]; // 拓撲排序後的順序
// 以鄰接矩陣存儲圖
bool toposort(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!vis[j]&&rd[j]==0){ // 沒有遍歷過且入度爲0
vis[j]=1;
topo[i]=j;
for(int k=1;k<=n;k++) // 刪除以這個點爲弧尾的邊,並將入度減1
if(w[j][k]){w[j][k]=0;rd[k]--;}
break;
}
}
}
for(int i=1;i<=n;i++) // 如果有節點沒有遍歷到,說明有環
if(!vis[i])return 0;
return 1;
}
歐拉路徑
int g[MAX][MAX]; // 鄰接矩陣存儲圖,元素爲結點間邊的數量
int d[MAX]; // 存儲結點的度
int path[MAX],p=0; // 存儲歐拉路徑
// 無向圖歐拉路徑
bool eulor(){
int cnt=0;
for(int i=1;i<=n;i++) // 並查集判斷圖是否連通
if(fa[i]==i)cnt++;
if(cnt!=1)return 0;
cnt=0;
for(int i=1;i<=n;i++) // 無向圖判斷是否只有兩個度爲奇數的結點(歐拉通路)
if(d[i]%2==1)cnt++; // 或者無度爲奇數的結點(歐拉回路)
if(cnt==0||cnt==2)return 1;
return 0;
}
// dfs求歐拉路徑
void dfs(int start){ // 給予歐拉路徑起始點
for(int j=1;j<=n;j++){
if(g[start][j]){
g[start][j]--;g[j][start]--;
dfs(j);
if(g[start][j])j--;
}
}
path[p++]=start; // 存儲歐拉路徑
}