zoukankan      html  css  js  c++  java
  • 二分图相关题

    HDU 1281

    由于每行最多放一个,每列最多放一个(不能放置的位置不影响攻击,就是由于没注意这句话,把这题当做行列覆盖模型做了好久0.0)

    所以把行列直接当做二分图X和Y集。能够放置的点的行列连边,求出的完备匹配就是第二个答案。

    至于第一个答案求关键点,就枚举删除一条边是否能任然得到完备匹配,若不行,则是关键点。

    我的代码c++会WA,不知道为什么。求教啊。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int mp[105][105];
    int to[105];
    bool vis[105];
    int n;
    int dfs(int k)
    {
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&mp[k][i])
            {
                vis[i]=1;
                if(to[i]==-1||dfs(to[i]))
                {
                    to[i]=k;
                    return 1;
                }
            }
        }
        return 0;
    }
    int a[100090],b[100900];
    int main()
    {
        int m,k,ca=1;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            memset(mp,0,sizeof(mp));
            for(int i=1;i<=k;i++)
            {
                scanf("%d%d",&a[i],&b[i]);
                mp[a[i]][b[i]]=1;
            }
            int ans=0;
            memset(to,-1,sizeof(to));
            for(int i=1;i<=n;i++)
            {
                memset(vis,0,sizeof(vis));
                ans+=dfs(i);
            }
            int ans2=0,tot=0;
            for(int i=1;i<=k;i++)
            {
                ans2=0;
                mp[a[i]][b[i]]=0;
    
                memset(to,-1,sizeof(to));
                for(int i=1;i<=n;i++)
                {
                    memset(vis,0,sizeof(vis));
                    ans2+=dfs(i);
                }
                if(ans2!=ans) tot++;
                mp[a[i]][b[i]]=1;
            }
            printf("Board %d have %d important blanks for %d chessmen.
    ",ca++,tot,ans);
        }
        return 0;
    }
    

    POJ 2062

    第一个人按顺序出牌,第二个人又一次排列后出牌,求最多得分。

    非常easy想到的二分图匹配,建图时写个函数比較一下牌的大小就够了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int mp[105][105];
    int to[555];
    bool vis[555];
    char s[10];
    char h[500];
    int n;
    int dfs(int k)
    {
        for(int i=0;i<n;i++)
        {
            if(!vis[i]&&mp[k][i])
            {
                vis[i]=1;
                if(to[i]==-1||dfs(to[i]))
                {
                    to[i]=k;
                    return 1;
                }
            }
        }
        return 0;
    }
    bool cmp(char *sa,char *sb)
    {
        if(h[sa[0]]==h[sb[0]]) return h[sa[1]]>h[sb[1]];
        return h[sa[0]]>h[sb[0]];
    }
    char sa[105][5],sb[105][5];
    int main()
    {
        h['H']=3;
        h['S']=2;
        h['D']=1;
        h['C']=0;
        for(int i='2';i<='9';i++) h[i]=i-'2';
        h['T']=8;
        h['J']=9;
        h['Q']=10;
        h['K']=11;
        h['A']=12;
        int cas;
        scanf("%d",&cas);
        while(cas--)
        {
            memset(mp,0,sizeof(mp));
            memset(to,-1,sizeof(to));
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s",sa[i]);
            }
            for(int i=0;i<n;i++)
            {
                scanf("%s",sb[i]);
            }
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                {
                    if(cmp(sb[j],sa[i])) mp[j][i]=1;
                }
            }
            int ans=0;
            for(int i=0;i<n;i++)
            {
                memset(vis,0,sizeof(vis));
                ans+=dfs(i);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    HDU 2119

    行列分为二分图。若相交位置有1则连一条容量为INF的边。其它边容量为1,最小割就是消除全部1的解

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #define eps  1e-12
    #define INF   0x7fffffff
    #define maxn 22222
    using namespace std;
    int n,m;
    int en;
    int st,ed;	//源点和汇点
    int dis[maxn] ;//dis[i],表示  到 原点  s 的 层数
    int que[9999999];
    struct edge
    {
    	int to,c,next;
    };
    edge e[9999999];
    int head[maxn];
    void add(int a,int b,int c)
    {
    	e[en].to=b;
    	e[en].c=c;
    	e[en].next=head[a];
    	head[a]=en++;
    	e[en].to=a;
    	e[en].c=0;
    	e[en].next=head[b];
    	head[b]=en++;
    }
    int bfs()
    {
        memset(dis,-1,sizeof(dis));
        dis[st]=0;
        int front=0,rear=0;
        que[rear++]=st;
        while(front<rear)
        {
            int j=que[front++];
            for(int k=head[j];k!=-1;k=e[k].next)
            {
                int i=e[k].to;
    			if(dis[i]==-1&&e[k].c)
                {
                    dis[i] = dis[j]+ 1 ;
                    que[rear++]=i;
                    if(i==ed) return true;
                }
            }
        }
        return false;
    }
    int dfs(int x,int mx)
    {
        int i,a;
        if(x==ed) return mx ;
    int ret=0;
        for(int k=head[x];k!=-1&&ret<mx;k=e[k].next)
        {
            if(e[k].c&&dis[e[k].to]==dis[x]+1)
            {
                int dd=dfs(e[k].to,min(e[k].c,mx-ret));
                e[k].c-=dd;
                e[k^1].c+=dd;
                ret+=dd;
            }
        }
        if(!ret) dis[x]=-1;
        return ret;
    }
    void init()
    {
        en=0;
    	st=0;     //源
        ed=n+m+10;     //汇
    	memset(head,-1,sizeof(head));
    }
    void build()
    {
        int x,y,z;
        for(int i=1;i<=n;i++) add(st,i,1);
        for(int j=1;j<=m;j++) add(j+n,ed,1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&x);
                if(x==1) add(i,j+n,INF);
            }
        }
    }
    int dinic()
    {
        int tmp=0;
        int maxflow=0;
        while(bfs())
        {
            while(tmp=dfs(st,INF)) maxflow+=tmp;
        }
        return maxflow;
    }
    int main()
    {
        while(scanf("%d",&n)&&n)
        {
            scanf("%d",&m);
            init();
            build();
            printf("%d
    ",dinic());
        }
    }
    


  • 相关阅读:
    bzoj2287 [POJ Challenge]消失之物
    bzoj4504 K个串
    Tjoi2016&Heoi2016 字符串
    bzoj2555 SubString
    WC2017 游记
    《大灌篮》观后感
    Codeforces Round #394 (Div. 2)
    bzoj3489 A simple rmq problem
    Goodbye Bingshen
    COGS2216 你猜是不是KMP
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6703254.html
Copyright © 2011-2022 走看看