图论总结

图论总结

二分图最大匹配

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 1010
bool 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");  
        }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值