時間複雜度 O(n+m), n表示點數,m表示邊數算法
(1) 深度優先遍歷 —— 模板題 AcWing 846. 樹的重心數組
int dfs(int u){ vis[u]=1; int son_size=1,now=0; ee(i,u){ int v=e[i].v; if(!vis[v]){ int t=dfs(v); now=max(now,t); son_size+=t; } } now=max(now,n-son_size); ans=min(ans,now); return son_size; }
(2) 寬度優先遍歷 —— 模板題 AcWing 847. 圖中點的層次優化
queue<int>q; inline void spfa(){ mem(dis,0x3f); mem(vis,0); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } }
拓撲排序 —— 模板題 AcWing 848. 有向圖的拓撲序列 時間複雜度 O(n+m), n表示點數,m表示邊數spa
queue<int>q; bool topo(){ rep(i,1,n) if(!deg[i]) q.push(i); while(!q.empty()){ int u=q.front();q.pop(); topon[++tot]=u; ee(i,u){ int v=e[i].v; if(--deg[v]==0) q.push(v); } } return tot==n; }
時間複雜度 O(mlogn), n表示點數,m表示邊數code
priority_queue<pair<int,int> >q; inline void dij(){ mem(dis,0x3f); mem(vis,0); q.push(make_pair(0,1)); dis[1]=0; while(!q.empty()){ int u=q.top().second;q.pop(); if(vis[u])continue; vis[u]=1; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; q.push(make_pair(-dis[v],v)); } } } }
時間複雜度 O(nm), n表示點數,m表示邊數排序
#define N 510 #define M 10010 int n,m,k; int dis[N],backup[N]; //使用backup數組的目的是爲了防止鬆弛的次數大於k struct Edge{ int u, v, w; }e[M]; inline int bellman_ford(){ mem(dis,0x3f); dis[1]=0; rep(i,1,k){ memcpy(backup,dis,sizeof(dis)); rep(j,1,m){ int u=e[j].u,v=e[j].v,w=e[j].w; if(backup[u]!=0x3f3f3f3f && dis[v]>backup[u]+w){ dis[v]=backup[u]+w; } } } if(dis[n]==0x3f3f3f3f)return -1; else return dis[n]; } int main(){ rd(n),rd(m),rd(k); rep(i,1,m){ rd(e[i].u),rd(e[i].v),rd(e[i].w); } int t=bellman_ford(); if (t==-1) puts("impossible"); else printf("%d\n", t); return 0; }
時間複雜度 平均狀況下 O(m),最壞狀況下 O(nm), n表示點數,m表示邊數隊列
queue<int>q; inline void spfa(){ mem(dis,0x3f); mem(vis,0); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } }
時間複雜度是 O(nm), n表示點數,m表示邊數it
#define N 100010 int head[N],tot,dis[N],cnt[N]; bool vis[N]; struct Edge{ int v,next,w; }e[N<<1]; void add(int u,int v,int w){e[++tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot;} int n,m,s; queue<int>q; inline bool spfa(int s){ mem(dis,0)//本題能夠不作初始化,但加上了也沒事,因此就加上唄 mem(vis,0); mem(cnt,0); rep(i,1,n){ vis[i]=1; q.push(i); }////判整個圖的負環要將每一個節點都加入 while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; cnt[v]=cnt[u]+1; if(cnt[v]>=n)return 1; if(!vis[v]){ vis[v]=1; q.push(v); } } } } return 0; } int main(){ rd(n),rd(m); rep(i,1,m){ int x,y,z;rd(x),rd(y),rd(z); add(x,y,z); } if(spfa(1)) printf("Yes\n"); else printf("No\n"); return 0; }
時間複雜度是 O(n^3) , n表示點數io
/* *若是有負權邊,雖然a,b不連通,但之間的距離也會由於負權邊的更新小於INF, 由於INF/2也是一個很大的數,因此就用>INF/2來表明不能連通 #define N 210 int dis[N][N]; int n,m,k; inline void floyd(){ rep(k,1,n) rep(i,1,n) rep(j,1,n) dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); } int main(){ rd(n),rd(m),rd(k); mem(dis,0x3f); rep(i,1,n)dis[i][i]=0;///////////////////////////// rep(i,1,m){ int x,y,z;rd(x),rd(y),rd(z); dis[x][y]=min(dis[x][y],z);/////////////////////// } floyd(); while(k--){ int x,y;rd(x),rd(y); if(dis[x][y]>0x3f3f3f3f/2)printf("impossible\n");/////////////////////// else printf("%d\n",dis[x][y]); } //printf("%d",0x3f3f3f3f); return 0; }
時間複雜度是 O(n^2+m), n表示點數,m表示邊數模板
int n; // n表示點數 int g[N][N]; // 鄰接矩陣,存儲全部邊 int dist[N]; // 存儲其餘點到當前最小生成樹的距離 bool st[N]; // 存儲每一個點是否已經在生成樹中
// 若是圖不連通,則返回INF(值是0x3f3f3f3f), 不然返回最小生成樹的樹邊權重之和 int prim() { memset(dist, 0x3f, sizeof dist);
int res = 0; for (int i = 0; i < n; i ++ ) { int t = -1; for (int j = 1; j <= n; j ++ ) if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; if (i && dist[t] == INF) return INF; if (i) res += dist[t]; st[t] = true; for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]); } return res;
}
時間複雜度是 O(mlogm), n表示點數,m表示邊數
#define N 100010 struct edge{ int u,v,w; bool operator < (const edge &rhs)const{ return w<rhs.w; } }e[N<<1]; int f[N],n,m,ans,cnt; inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);} inline void kruskal(){ sort(e+1,e+m+1); rep(i,1,n)f[i]=i; rep(i,1,m){ int fx=find(e[i].u),fy=find(e[i].v); if(fx==fy)continue; f[fx]=fy; ans+=e[i].w; if(++cnt==n-1)break; } } #undef int int main(){ #define int long long #ifdef WIN32 freopen("","r",stdin); #endif rd(n),rd(m); rep(i,1,m){ rd(e[i].u),rd(e[i].v),rd(e[i].w); } kruskal(); if(cnt<n-1)printf("impossible\n"); else printf("%lld\n",ans); return 0; }
時間複雜度是 O(n+m), n表示點數,m表示邊數
#define N 200010 #define M int head[N],tot,col[N],s1,cnt,n,m; bool vis[N]; //col 表示每一個點的顏色,-1表示未染色,-2表示白色,1表示黑色 struct edge{ int v,w,next; }e[N<<1]; inline void add(int u,int v){e[++tot].v=v;e[tot].next=head[u];head[u]=tot;} queue<pair<int,int> >q; inline bool bfs(){ col[1]=1; q.push(make_pair(1,1)); while(!q.empty()){ int u=q.front().first; int color=q.front().second; q.pop(); ee(i,u){ int v=e[i].v; if(col[v]==-1){ col[v]=~color; q.push(make_pair(v,col[v])); } else if(col[v]==col[u])return 0; } } return 1; } int main(){ //freopen("erfen.txt","r",stdin); rd(n),rd(m); rep(i,1,m){ int u,v;rd(u),rd(v); add(u,v),add(v,u); } mem(col,-1); if(bfs())printf("Yes\n"); else printf("No\n"); return 0; } /* 4 4 1 3 1 4 2 3 2 4 */ //Yes //col的值有三種,-1(初始值),-2,1;
時間複雜度是 O(nm), n表示點數,m表示邊數
#define N 510 #define M 100010 int head[N],cnt; struct edge{ int v,next; }e[M]; inline void add(int u,int v){e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} int match[N]; bool vis[N];//考慮過 int n1,n2,m,ans; inline bool dfs(int u){ ee(i,u){ int v=e[i].v; if(!vis[v]){ vis[v]=1; if(match[v]==0 || dfs(match[v])){ match[v]=u; return 1; } } } return 0; } #undef int int main(){ #define int long long //freopen("erfen.txt","r",stdin); rd(n1),rd(n2),rd(m); while(m--){ int u,v;rd(u),rd(v); add(u,v); } mem(match,0); rep(i,1,n1){ mem(vis,0); if(dfs(i)) ans++; } printf("%lld",ans); return 0; }