二分图最大匹配:网络流做法——模板题

二分图最大匹配网络流做法

  • 二分图最大匹配网络流做法
    • 题意
    • 思路
    • 代码

题意

自己学校的OJ,题目大意是给定totline个数对x,y,表示x可以和y搭配,数据保证一个数x出现在右边最不会出现在左边

思路

人为增加难度2333,二分图最大匹配使用网络流来做,为什么可行呢?
这个图片是二分图最大匹配的解释图
二分图最大匹配:网络流做法——模板题_第1张图片
本质就是求从左到右有多少对。
那么我们把左边的点连到一个超级源点,右边连到超级汇点,然后有这张图:
二分图最大匹配:网络流做法——模板题_第2张图片
那么网络流这里求的是…
从左边到右边一共有几个边(每个点最大流量是1)
注意这里是每个点,所以要经过一些处理
(所以我用邻接矩阵偷懒XD)
顺便说一句,我被数组开小了坑了足足一个中午的时光,maxnode>1002,我开了1001…
使用链式前向星储存的人们请注意!超级源点到各点之间的最大流量请设为1!因为为0x7ffff时一个红点将可以和0x7ffff和蓝点连接!
以下是AC程序源码

代码

#include
#include
#include
#include
//#define max(x,y) x>y?x:y
//#define min(x,y) x
using namespace std;
/*const&int*/
const int maxnode=1008;
const int maxline=3001;
int totnode,totline;
int ans;
/*ljjz*/
int can[maxnode][maxnode];
/*dinic*/
queue<int> team;
int ceng[maxnode];
int superS,superE;
/*---cut---*/
inline void read(int &x){  
    char c=getchar();x=0;int flag=0;  
    while((c>'9'||c<'0')&&c!='-') c=getchar();  
    if(c=='-'){flag=1;c=getchar();}  
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}  
    if(flag)x=-x;  
}  

inline void write(int x){  
    if(x<0){putchar('-');x=-x;}  
    if(x/10)write(x/10);  
    putchar((x%10)+'0');  
}  

inline void writeln(int x){  
    write(x);putchar('\n');  
}  

bool Dinic_BFS(int startnode)
{
    memset(ceng,-1,sizeof(ceng));
    while(!team.empty()) team.pop();

    team.push(startnode);
    ceng[startnode]=0;

    int i;
    int teamhead;
    while(!team.empty())
    {
        teamhead=team.front();
        team.pop();

        for(i=0;i<=totnode+2;++i)
        {
            if(can[teamhead][i]>0&&ceng[i]==-1)
            {
                team.push(i);
                ceng[i]=ceng[teamhead]+1;
            }
        }
    }
    if(ceng[superE]==-1) return 0;
    return 1;
}

int Dinic_ZG(int nownode,int wave)
{
    if(nownode==superE) return wave;


    int tmp;
    for(int i=0;i<=totnode+2;++i)
    {
        if(can[nownode][i]>0&&ceng[i]==ceng[nownode]+1)
        {
            if((tmp=Dinic_ZG(i,1)))
            {
                //printf("%d\n",tmp);
                can[nownode][i]-=tmp;
                can[i][nownode]+=tmp;
                return tmp;
            }
        }
    }
    return 0;
}

int main()
{
    //freopen("cp.out","w",stdout);
    read(totnode);read(totline);
    int x,y;
    superS=totnode+2;
    superE=totnode+1;

    for(int i=1;i<=totline;++i)
    {
        read(x);read(y);
        can[x][y]=1;
        can[superS][x]=1;
        can[y][superE]=1;
    }

    int tmp;
    while(Dinic_BFS(superS))
    {
        while((tmp=Dinic_ZG(superS,1)))
        {
            ans+=tmp;
        }
    }
    printf("%d\n",ans);
}

你可能感兴趣的:(网络流,+++++算法+++++)