图论总结(持续更新)
来源:互联网 发布:通达信的软件 编辑:程序博客网 时间:2024/06/07 01:50
- 图论总结
- 二分图最大匹配
- km最大权最小权
- 最大流
- 最小费用最大流
- 强联通分量
- 割点点双联通
- 割边边双联通
- 最大团
- 带权并查集
图论总结
二分图最大匹配
int match[MAXN];bool vis[MAXN];bool dfs(int u){ for(int v = 1; v <= b; ++v) { if(!vis[v]&&!tu[u][v]) { vis[v] = 1; if(match[v] == -1 || dfs(match[v])) { match[v] = u; return 1; } } } return 0;}
km最大权最小权
int w[MAXN][MAXN1],pre[MAXN1],kx[MAXN],ky[MAXN1]; bool visx[MAXN1],visy[MAXN1]; void init() { memset(ky,0,sizeof(ky)); memset(pre,-1,sizeof(pre)); for(int i=0; i<n; ++i) { kx[i]=w[i][0]; for(int j=1; j<m; ++j) { kx[i]=max(kx[i],w[i][j]); } } } bool dfs(int u) { visx[u]=1; for(int i=0; i<m; ++i) { if(!visy[i]) { int t=kx[u]+ky[i]-w[u][i]; if(!t) { visy[i]=1; if(pre[i]==-1||dfs(pre[i])) { pre[i]=u; return 1; } } else d=min(d,t); } } return 0; } int km() { for(int i=0; i<n; ++i) { while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); d=inf; if(dfs(i))break; for(int j=0; j<m; ++j) { if(visx[j])kx[j]-=d; if(visy[j])ky[j]+=d; } } } int ans=0; for(int i=0; i<m; ++i) { if(pre[i]!=-1)ans+=w[pre[i]][i]; } return -ans; }
最大流
struct node { int u,v,f; int next; } edge[MAXN*520]; int head[MAXN]; int cnt; void add(int u,int v,int f) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].f=f; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].f=0; edge[cnt].next=head[v]; head[v]=cnt++; } int dis[MAXN]; int bfs(int s,int t) { int u, v ; memset(dis,-1,sizeof(dis)); dis[s] = 0 ; queue<int>q; q.push(s) ; while( !q.empty() ) { u = q.front(); q.pop(); for(int i = head[u] ; i != -1 ; i = edge[i].next) { v = edge[i].v ; if( dis[v] == -1 && edge[i].f ) { dis[v] = dis[u] + 1 ; q.push(v) ; } } } if( dis[t] > 0 ) return 1 ; return 0 ; } int dfs(int s,int t,int min1) { if( s == t ) return min1 ; int flow, ans = 0 ; for(int i = head[s] ; i != -1 ; i = edge[i].next) { int v = edge[i].v ; if( dis[v] == dis[s] + 1 && edge[i].f && (flow = dfs(v,t,min(min1,edge[i].f) ) ) ) { edge[i].f -= flow ; edge[i^1].f += flow ; ans += flow ; min1 -= flow ; if( !min1 ) break; } } if( ans ) return ans ; dis[s] = -1 ; return 0; } int getMaxFlow() { int maxFlow=0,flow; while(bfs(s,e)) { while((flow=dfs(s,e,inf))>0) maxFlow+=flow; } return maxFlow; }
最小费用最大流
int cnt,head[MAXN]; struct node { int u,v,w,f,next; } edge[8000]; void init() { cnt=0; for(int i=0; i<=e; ++i)head[i]=-1;} void add(int u,int v,int w,int f) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].f=f; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].w=-w; edge[cnt].f=0; edge[cnt].next=head[v]; head[v]=cnt++; } bool vis[MAXN]; int dis[MAXN],pre[MAXN]; bool spfa() { int i; for(i=0; i<=e; ++i) { dis[i]=inf; pre[i]=-1; vis[i]=0; } queue<int>q; q.push(0); dis[0]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; int f=edge[i].f; if(f>0&&dis[v]>dis[u]+w) { dis[v]=dis[u]+w; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(pre[e]==-1)return 0; return 1; } int get_mincost() { int max_flow=0,min_cost=0; while(spfa()) { int p=pre[e]; int flow=inf; while(p!=-1) { flow=min(flow,edge[p].f); p=pre[edge[p].u]; } max_flow+=flow; min_cost+=flow*dis[e]; p=pre[e]; while(p!=-1) { edge[p].f-=flow; edge[p^1].f+=flow; p=pre[edge[p].u]; } } return min_cost; }
强联通分量
vector<int>head[MAXN],G[MAXN]; int dfn[MAXN],sccno[MAXN],sum[MAXN],dfs_clock,scc_cnt; stack<int>S; int dfs(int u) { int lowu=dfn[u]=++dfs_clock; S.push(u); for(int i=0,l=head[u].size(); i<l; ++i) { int v=head[u][i]; if(!dfn[v]) { int lowv=dfs(v); lowu=min(lowu,lowv); } else if(!sccno[v]) { lowu=min(lowu,dfn[v]); } } if(lowu==dfn[u]) { scc_cnt++; while(1) { int x=S.top(); S.pop(); sccno[x]=scc_cnt; if(x==u)break; } } return lowu; } void find_scc() { dfs_clock=scc_cnt=0; fill(dfn+1,dfn+1+n,0); fill(sccno+1,sccno+1+n,0); for(int i = 1; i <= n; ++i)if(!dfn[i])dfs(i); }
割点点双联通
struct Edge { int u,v; Edge(int x,int y) { u=x; v=y; } }; //查找双联通分量 int pre[MAXN],bccno[MAXN],iscut[MAXN],sum[MAXN],dfs_clock,bcc_cnt; vector<int>G[MAXN],bcc[MAXN]; stack<Edge>S; int dfs(int u,int fa) { int lowu=pre[u]=++dfs_clock; int child=0,l=G[u].size(); for(int i=0; i<l; ++i) { int v=G[u][i]; Edge e=Edge(u,v); if(!pre[v]) { S.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>=pre[u]) { iscut[u]=1; bcc_cnt++; while(1) { Edge x=S.top(); S.pop(); if(bccno[x.u]!=bcc_cnt) { bccno[x.u]=bcc_cnt; sum[x.u]++; } if(bccno[x.v]!=bcc_cnt) { bccno[x.v]=bcc_cnt; sum[x.v]++; } if(x.u==u&&x.v==v)break; } } } else if(pre[u]>pre[v]&&v!=fa) { S.push(e); lowu=min(lowu,pre[v]); } } if(fa<0&&child==1)iscut[u]=0; return lowu; } void find_bcc() { int i; for(i=1; i<=n; ++i) { pre[i]=bccno[i]=iscut[i]=sum[i]=0; } bcc_cnt=dfs_clock=0; for(i=1; i<=n; ++i)if(!pre[i])dfs(i,-1); }
割边边双联通
int dfn[MAXN],bccno[MAXN],bridge[MAXN][MAXN],dfs_clock,bcc_cnt; int dfs(int u,int fa) { int lowu=dfn[u]=++dfs_clock; for(int i=0,l=G[u].size(); i<l; ++i) { int v=G[u][i]; if(!dfn[v]) { int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>dfn[u]) { bridge[u][v]=bridge[v][u]=1; } } else if(dfn[u]>dfn[v]&&v!=fa) { lowu=min(lowu,dfn[v]); } } return lowu; } void find_bridge() { for(int i=0; i<n; ++i) { dfn[i]=0; bccno[i]=0; for(int j=i+1; j<n; ++j)bridge[i][j]=bridge[j][i]=0; } dfs_clock=bcc_cnt=0; for(int i=0; i<n; ++i)if(!dfn[i])dfs(i,-1); } int vis[MAXN]; void dfse(int u,int x) { bccno[u]=x; vis[u]=1; for(int i=0,l=G[u].size(); i<l; ++i) { int v=G[u][i]; if(!vis[v]&&!bridge[u][v]) { dfse(v,x); } } } void find_bcc() { for(int i=0; i<n; ++i)vis[i]=0; for(int i=0; i<n; ++i)if(!vis[i])dfse(i,++bcc_cnt); }
最大团
#include<cstdio>#include<cstring>#define N 1010bool flag[N], a[N][N];int ans, cnt[N], group[N], n, vis[N];// 最大团: V中取K个顶点,两点间相互连接// 最大独立集: V中取K个顶点,两点间不连接 // 最大团数量 = 补图中最大独立集数bool dfs( int u, int pos ){ int i, j; for( i = u+1; i <= n; i++){ if( cnt[i]+pos <= ans ) return 0; if( a[u][i] ){ // 与目前团中元素比较,取 Non-N(i) for( j = 0; j < pos; j++ ) if( !a[i][ vis[j] ] ) break; if( j == pos ){ // 若为空,则皆与 i 相邻,则此时将i加入到 最大团中 vis[pos] = i; if( dfs( i, pos+1 ) ) return 1; } } } if( pos > ans ){ for( i = 0; i < pos; i++ ) group[i] = vis[i]; // 最大团 元素 ans = pos; return 1; } return 0;} void maxclique(){ ans=-1; for(int i=n;i>0;i--) { vis[0]=i; dfs(i,1); cnt[i]=ans; }}
带权并查集
int findx(int x) { if(pre[x]==x) { return x; } int order=pre[x]; pre[x]=findx(pre[x]); relation[x]=(relation[x]+relation[order])%2; return pre[x]; } if(a!=b)//关系还没有建立过 { puts("YES"); //更新结点值 pre[b]=a; relation[b]=(relation[x]-relation[y]+z+2)%2; } else//关系已经建立 { int p=(relation[x]-relation[y]+2)%2;//得到关系 if(p==z)puts("YES"); else puts("NO"); }
阅读全文
0 0
- 图论总结(持续更新)
- 项目总结(持续更新)
- 错误总结(持续更新)
- LeetCode || 总结(持续更新)
- DP总结(持续更新)
- 数论总结(持续更新)
- STL总结(持续更新)
- ArcEngine 总结(持续更新)
- 数论总结(持续更新)
- java总结(持续更新)
- 【专题总结】网络流与二分图(持续更新)
- 图论基础算法(持续更新)
- Xcode的小总结(持续更新)
- unix常用命令总结(持续更新)
- ubuntu 使用命令总结(持续更新)
- 题目总结(持续更新中)
- C++ 异常使用总结(持续更新)
- 经济 词汇总结 (持续更新中)
- STL之Stack
- <数据结构与算法>之二叉查找树
- servlet的映射路径
- banner轮播
- 牛客网---2016---去哪儿文本嗅探
- 图论总结(持续更新)
- Hadoop之namenode-yellowcong
- 61. Rotate List
- Java反序列化时报异常java.io.EOFException
- <context:component-scan>使用详情
- iOS TranslationZoom(平移 缩放 弹性)~demo
- hdu 6119 小小粉丝度度熊(交叉区间去重)
- python 文件操作
- java的http请求的书写