zoukankan      html  css  js  c++  java
  • hdu 4687 带花树匹配

    其实吧,思路挺简单的,只不过昨天刚学,还有一些东西不太了解,然后就23333333.。。

    吃晚饭回来就A了,我是有多傻啊,这么题都A不掉,不能忍啊。。。

    我们可以先求出哪些边是可能存在于最大匹配中的,然后剩下的边就是绝对不可能在最大匹配中了

    求哪些边可能存在于最大匹配中,超简单,只需要强制将那条边上的两个点匹配(即删除),然后求最大匹配,如果是tot-1,那么这条边就可以存在于最大匹配中。

    ps:比赛的时候直接match[u]=v match[v]=u了,队友其实给我提供过正确的思路,只不过我太傻x,说多了都是泪。。。

    /* **********************************************
    Author      : wuyiqi
    Created Time: 2013-8-20 15:55:42
    File Name   : 1002.cpp
    *********************************************** */
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    //#define MAXE 300*300*2
    #define MAXN 300
    #define SET(a,b) memset(a,b,sizeof(a))
    deque<int> Q;
    //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
    bool g[MAXN][MAXN],inque[MAXN],inblossom[MAXN];
    int match[MAXN],pre[MAXN],base[MAXN];
     
    //找公共祖先
    int findancestor(int u,int v)
    {
        bool inpath[MAXN]={false};
        while(1)
        {
            u=base[u];
            inpath[u]=true;
            if(match[u]==-1)break;
            u=pre[match[u]];
        }
        while(1)
        {
            v=base[v];
            if(inpath[v])return v;
            v=pre[match[v]];
        }
    }
     
    //压缩花
    void reset(int u,int anc)
    {
        while(u!=anc)
        {
            int v=match[u];
            inblossom[base[u]]=1;
            inblossom[base[v]]=1;
            v=pre[v];
            if(base[v]!=anc)pre[v]=match[u];
            u=v;
        }
    }
     
    void contract(int u,int v,int n)
    {
        int anc=findancestor(u,v);
        SET(inblossom,0);
        reset(u,anc);reset(v,anc);
        if(base[u]!=anc)pre[u]=v;
        if(base[v]!=anc)pre[v]=u;
        for(int i=1;i<=n;i++)
            if(inblossom[base[i]])
            {
                base[i]=anc;
                if(!inque[i])
                {
                    Q.push_back(i);
                    inque[i]=1;
                }
            }
    }
     
    bool dfs(int S,int n)
    {
        for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;
        Q.clear();Q.push_back(S);inque[S]=1;
        while(!Q.empty())
        {
            int u=Q.front();Q.pop_front();
            for(int v=1;v<=n;v++)
            {
                if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
                {
                    if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
                    else if(pre[v]==-1)
                    {
                        pre[v]=u;
                        if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
                        else
                        {
                            u=v;
                            while(u!=-1)
                            {
                                v=pre[u];
                                int w=match[v];
                                match[u]=v;
                                match[v]=u;
                                u=w;
                            }
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
     
    int solve(int n)
    {
        SET(match,-1);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(match[i]==-1&&dfs(i,n))
                ans++;
        return ans;
    }
    bool vis[200];
    int a[200],b[200];
    bool mp[200][200];
    int main() {
        int n , m;
        while(scanf("%d%d",&n,&m) != EOF) {
           memset(g,false,sizeof(g));
           memset(vis,false,sizeof(vis));
           memset(mp,false,sizeof(mp));
           for(int i = 1; i <= m; i++) {
               scanf("%d%d",&a[i],&b[i]);
               g[a[i]][b[i]] = g[b[i]][a[i]] = true;
               mp[a[i]][b[i]] = mp[b[i]][a[i]] = true;
           }
           int ans = solve(n);
           for(int i = 1; i <= m; i++) {
               int x = a[i]  , y = b[i];
               memset(g,false,sizeof(g));
               for(int j = 1; j <= m; j++) if(i!=j){
                   if(a[j] == y && b[j] == x) continue;
                   int aa = a[j] , bb = b[j];
                   if(aa==x || aa==y || bb==x || bb==y) continue;
                   g[aa][bb] = g[bb][aa] = true;
               }
               int tmp = solve(n);
               if(tmp == ans - 1) {
                   vis[i] = true;
               }
           }
           vector<int> ret;
           for(int i = 1; i <= m; i++) if(!vis[i]) {
               ret.push_back(i);
           }
           printf("%d
    ",ret.size());
           if(ret.size()>0) {
               printf("%d",ret[0]);
               for(int i = 1; i < ret.size(); i++) {
                   printf(" %d",ret[i]);
               }
           }
           puts("");
        }
        return 0;
    }
    


  • 相关阅读:
    yzoj P2344 斯卡布罗集市 题解
    yzoj P2350 逃离洞穴 题解
    yzoj P2349 取数 题解
    JXOI 2017 颜色 题解
    NOIP 2009 最优贸易 题解
    CH 4302 Interval GCD 题解
    CH4301 Can you answer on these queries III 题解
    Luogu2533[AHOI2012]信号塔
    Luogu3320[SDOI2015]寻宝游戏
    Luogu3187[HNOI2007]最小矩形覆盖
  • 原文地址:https://www.cnblogs.com/riskyer/p/3271301.html
Copyright © 2011-2022 走看看