- 图论总结
- 二分图最大匹配
- 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; i0];
for(int j=1; jbool dfs(int u)
{
visx[u]=1;
for(int i=0; iif(!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; iwhile(1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
d=inf;
if(dfs(i))break;
for(int j=0; jif(visx[j])kx[j]-=d;
if(visy[j])ky[j]+=d;
}
}
}
int ans=0;
for(int i=0; iif(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(); iint 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];
stackS;
int dfs(int u,int fa)
{
int lowu=pre[u]=++dfs_clock;
int child=0,l=G[u].size();
for(int i=0; iint 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(); iint 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; i0;
bccno[i]=0;
for(int j=i+1; j0;
}
dfs_clock=bcc_cnt=0;
for(int i=0; iif(!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(); iint v=G[u][i];
if(!vis[v]&&!bridge[u][v])
{
dfse(v,x);
}
}
}
void find_bcc()
{
for(int i=0; i0;
for(int i=0; iif(!vis[i])dfse(i,++bcc_cnt);
}
最大团
#include
#include
#define N 1010
bool flag[N], a[N][N];
int ans, cnt[N], group[N], n, vis[N];
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] ){
for( j = 0; j < pos; j++ ) if( !a[i][ vis[j] ] ) break;
if( j == pos ){
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");
}