zoukankan      html  css  js  c++  java
  • 二分图

    1.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define N 202
    
    using namespace std;
    int Li[N],vis[N],con[N][N];
    int n,m,ans,f,x;
    
    bool dfs(int x)
    {
        for(int i=1;i<=m;i++)
        {
            if(con[x][i] && !vis[i])
            {
                vis[i]=1;
                if(!Li[i] || dfs(Li[i]))
                {
                    Li[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&f);
            for(int j=1;j<=f;j++)
            {
                scanf("%d",&x);
                con[i][x]=1;
            }
        }
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof vis);
            if(dfs(i)) ans++;
        }
        printf("%d
    ",ans);
        return 0;
    }
    P1894

     2.

    /*
    开始把边取反,然后跑一边匈牙利算法,然后判断是不是完美匹配(概念网上自己去找),不是就直接输出none;
    第二步每次删掉一条边,判断是不是完美匹配,不是就输出这个两个点;
    第二步跑完之后没有发现有一个是可以输出的,就输出none;
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    
    #define N 555
    
    using namespace std;
    int mx[N],Li[N],head[N];
    int n,cut_x,cut_y,S[N],T[N],num,flag=0;
    bool vis[N],k[N][N];
    struct node
    {
        int u;
        int to;
        int next;
    } e[N<<1];
    
    void add(int u,int to)
    {
        e[++num].to=to;e[num].next=head[u];head[u]=num;
    }
    
    int dfs(int x)
    {
        int v;
        for (int i=head[x];i!=0;i=e[i].next)
        {
            v=e[i].to;
            if(x==cut_x && v==cut_y) continue;
            if(vis[v]==true) continue;
            vis[v]=true;
            if(Li[v]==0 || dfs(Li[v]) )
            {
                mx[x]=v;
                Li[v]=x;
                return 1;
            }
        }
        return 0;
    }
    
    int maxmatch()
    {
        int ans=0;
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++) vis[j]=false;
            ans+=dfs(i);
        }
        return ans;
    }
    
    void Impotant_edge()
    {
        int ans;
        for (int i=1;i<=n;i++)
        {
            S[i]=i;T[i]=mx[i];
        }
        for (int i=1;i<=n;i++)
        {
            cut_x=S[i];cut_y=T[i];
            for (int j=1;j<=n;j++) mx[j]=0,Li[j]=0;
            ans=maxmatch();
            if (ans!=n)
            {
                printf("%d %d
    ",cut_x,cut_y);
                flag=1;
            }
        }
        return;
    }
    
    int main()
    {
        int ans,x,y;
        scanf("%d",&n);
        while(1)
        {
            scanf("%d%d",&x,&y);
            if (x==0&&y==0) break;
            k[x][y]=1;
        }
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                if( k[i][j]==0 ) add(i,j);
        ans=maxmatch();
        if (ans!=n)
        {
            cout<<"none"<<endl;
            return 0;
        }
        else
        {
            Impotant_edge();
            if (flag==0)  cout<<"none"<<endl;
            return 0;
        }
    }
    codevs1222

     3

    /*
    这道题显然是求最长反链, 
    最长反链=最小链覆盖.最小链覆盖就是先做一次floyd传递闭包, 再求最小路径覆盖. 
    最小路径覆盖=N - 二分图最大匹配.
     所以把所有点拆成x,y两个, 然后存在edge(u,v)就连ux->vy. 然后跑匈牙利即可.
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define N 207
    
    using namespace std;
    int n,m,ans,x,y;
    int f[N][N],Li[N],a[N][N];
    bool vis[N];
    
    void floyd()
    {
        for(int k=1;k<=n;k++)
          for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
              f[i][j]|=f[i][k]&f[k][j];
    }
    
    bool dfs(int x)
    {
        for(int i=1;i<=n;i++)
        {
            if(f[x][i] && !vis[i])
            {
                vis[i]=true;
                if(!Li[i] || dfs(Li[i]))
                {
                    Li[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            f[x][y]=1;
        }
        floyd();
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof vis);
            if(dfs(i)) ans++;
        }
        printf("%d
    ",n-ans);
        return 0;
        return 0;
        return 0;
    }
    bzoj1143(2718)

     4.

    /*
    二分图输出方案 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define MAX 200
    #define MAXL 200*200
    
    using namespace std;
    struct Line
    {
        int v,next;
    } e[MAXL];
    int head[MAX],Li[MAX];
    int n,m,u,v,sum,cnt;
    bool vis[MAX];
    inline void Add(int u,int v)
    {
        e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;
    }
    bool dfs(int u)
    {
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if(!vis[v])
            {
                vis[v]=true;
                if(!Li[v]||dfs(Li[v]))
                {
                    Li[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        while(1)
        {
            scanf("%d%d",&u,&v);
            if(u==-1)break;
            Add(u,v);
        }
        for(int i=1; i<=n; ++i)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i)) ++sum;
        }
        printf("%d
    ",sum);
        for(int i=n+1; i<=m; ++i)
          if(Li[i]) printf("%d %d
    ",Li[i],i);
        return 0;
        return 0;
        return 0;
    }
    洛谷P2756

    5.

    #include<iostream>
    
    #include<cstdio>
    
    #include<cstring>
    
    using namespace std;
    
    int n,m,q[5001][5001],d[5001],g[5001],sum;
    int map[5001][5001],march[5001],flag[5001],xv[5001];
    
    int dfs(int v)
    {
        for(int i=1; i<=n; i++)
        {
            if(map[v][i]==1&&flag[i]==0)
            {
                flag[i]=1;
                if(march[i]==0||dfs(march[i]))
                {
                    march[i]=v;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        cin>>n;
        int t;
        for(int i=1; i<=n; i++)
        {
            cin>>g[i];
            for(int j=1; j<=g[i]; j++)
                cin>>q[i][j];
        }
        cin>>m;
        for(int i=1; i<=m; i++)
        {
            cin>>xv[i];
            for(int j=1; j<=n; j++)
            {
                for(int k=1; k<=g[j]; k++)
                {
                    if(q[j][k]==xv[i])map[xv[i]][j]=1;
                }
            }
        }
        for(int i=1; i<=m; i++)
        {
            memset(flag,0,sizeof(flag));
            if(dfs(xv[i]))sum++;
        }
        cout<<sum;
        return 0;
    }
    codevs2930

     6.

    /*
    其实很简单,做两个二分图即可。
    可以构造两个二分图,依次从某一个客人出发同时对两个二分图寻找增广路
    若对某一个二分图没有找到增广路,则恢复从该客人出发找到的所有增广路(这条不行),
    反之,则改进匹配。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 101
    
    using namespace std;
    int n,p,q,i,j,RL[N][N],FL[N][N],LB[N],book[N],answer,eat[N];
    bool CR[N],visR[N],visF[N],LCR[N],CF[N];
    
    bool room_(int No)
    {
        for (int i=1; i<=n; i++)
            if (RL[No][i]&&!visR[i])
            {
                visR[i]=1;
                if (book[i]==0||room_(book[i]))
                {
                    CR[No]=1;
                    book[i]=No;
                    return 1;
                }
            }
        return 0;
    }
    
    bool food_(int No)
    {
        for (int i=1; i<=n; i++)
            if (FL[No][i]&&!visF[i])
            {
                visF[i]=1;
                if (eat[i]==0||food_(eat[i]))
                {
                    CF[No]=1;
                    eat[i]=No;
                    return 1;
                }
            }
        return 0;
    }
    
    int main ()
    {
        scanf("%d%d%d",&n,&p,&q);
        for (i=1; i<=n; i++)
            for (j=1; j<=p; j++)
                scanf("%d",&RL[i][j]);
        for (i=1; i<=n; i++)
            for (j=1; j<=q; j++)
                scanf("%d",&FL[i][j]);
        while (1)
        {
            for (i=1; i<=n; i++)
                if (!CR[i])
                {
                    for (j=1; j<=n; j++) visR[j]=0;
                    for (j=1; j<=n; j++) visF[j]=0;
                    for (j=1; j<=n; j++) LCR[j]=CR[j];
                    for (j=1; j<=n; j++) LB[j]=book[j];
                    if (room_(i)&&food_(i))
                    {
                        answer++;
                        continue;
                    }
                    else//因为无法匹配所以取消上次所有增广 
                    {
                        for (j=1; j<=n; j++) CR[j]=LCR[j];
                        for (j=1; j<=n; j++) book[j]=LB[j];
                    }
                }
            break;
        }
        printf("%d
    ",answer);
        return 0;
        return 0;
        return 0;
    }
    洛谷P1402
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    FSLIB.NETWORK 简易使用指南
    在CentOS上安装owncloud企业私有云过程
    用于ViEmu的重置为试用状态的Python脚本
    Microsoft.Office.Interop.Excel 报错
    FineUIMvc表格数据库分页,使用CYQ.Data组件
    如何在已有项目中引入FineUIMvc
    按键精灵-常用脚本命令汇集
    微信分享代码
    [教程] 【原创】媒体扫描耗电的彻底解决办法(申精)
    Less学习笔记
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7324178.html
Copyright © 2011-2022 走看看