• Benelux Algorithm Programming Contest 2016 Preliminary K. Translators’ Dinner(思路)


    题意:

    n种语言,m个翻译官,每个翻译官会2种语言,会同一种语言的2个翻译官可以放在一组

    问能否将所有的翻译官两两配对

    输出方案

    n<=100 m<=200

    保证没有2个翻译官会完全相同的2种语言

    我看了半天题解没看懂

    大佬分分钟用另一种思路秒杀题解

    tqltqltql%%%%%%%%%%%%%

    将语言看做点,翻译官看作边

    构图之后,如果每个连通块都是偶数条边,那么一定有一种解的方案

    考虑为每一个连通块构造方案

    枚举其中一条边,枚举它的配对边

    如果删去这两条边后,剩余的点和边仍然满足每个连通块都是偶数条边,即仍然有解的方案

    那就找到了它的匹配边

    复杂度是三次方级别的

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    #include<cstdio>
    #include<cstring>
     
    using namespace std;
    
    #define N 101
    #define M 201
    
    int n,m;
    int a[M],b[M],d[N];
    bool cut[M];
    
    int f[N];
    int siz[N];
    
    bool doo[N];
    int match[M];
    
    int ff[N];
    
    int find(int i) { return f[i]==i ? i : f[i]=find(f[i]); }
    
    int find2(int i) { return ff[i]==i ? i : ff[i]=find2(ff[i]); }
    
    bool judge()
    {
        for(int i=1;i<=n;++i) ff[i]=i;
        memset(siz,0,sizeof(siz));
        memset(d,0,sizeof(d));
        int p,q;
        for(int i=1;i<=m;++i)
            if(!cut[i])
            {
                d[a[i]]++;
                d[b[i]]++;
                p=find2(a[i]);
                q=find2(b[i]);    
                ff[p]=q;
            }
        for(int i=1;i<=n;++i) siz[find2(i)]+=d[i];
        for(int i=1;i<=n;++i)
            if(find2(i)==i && siz[i]/2&1) return false;
        return true; 
    }
    
    int solve(int x)
    {
        for(int i=1;i<=m;++i)
            if(i!=x && !match[i])
                if(a[x]==a[i] || a[x]==b[i] || b[x]==a[i] || b[x]==b[i])
                {
                    cut[x]=cut[i]=true;
                    if(judge()) return i;
                    cut[x]=cut[i]=false;
                }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) f[i]=i;
        int fa,fb;
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&a[i],&b[i]);
            ++a[i];
            ++b[i];
            d[a[i]]++;
            d[b[i]]++;
            fa=find(a[i]);
            fb=find(b[i]);
            f[fa]=fb;
        }
        for(int i=1;i<=n;++i)
            siz[find(i)]+=d[i];
        for(int i=1;i<=n;++i)
            if(find(i)==i && siz[i]/2&1 )
            {
                printf("impossible");
                return 0;
            }
        int g;
        for(int i=1;i<=n;++i)
            if(f[i]==i)
            {
                for(int j=1;j<=n;++j)
                    if(f[j]==i) doo[j]=true;
                for(int j=1;j<=m;++j)
                    if(!match[j] && doo[a[j]] && doo[b[j]])
                    {
                        g=solve(j);
                        match[j]=g;
                        match[g]=j;
                    }
                memset(doo,false,sizeof(doo));
            }
        for(int i=1;i<=m;++i)
            if(i<match[i]) printf("%d %d
    ",i-1,match[i]-1);    
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    功能测试点总结
    SQL 注入
    软件特征功能测试过程分析 (引用)
    高效率测试之巧用策略模式 (引用)
    Oracle数据库安装过程中遇到的若干问题
    涉众利益分析
    问题账户需求分析
    2018春阅读计划
    《我们应当怎样做需求分析》阅读笔记
    个人总结
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/13641706.html
Copyright © 2020-2023  润新知