• codevs1222 信与信封问题


    1222 信与信封问题

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
    题目描述 Description

    John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出。但是,第二天John的儿子Small John将这n封信都拿出了信封。不幸的是,Small John无法将拿出的信正确地装回信封中了。

     

    将Small John所提供的n封信依次编号为1,2,…,n;且n个信封也依次编号为1,2,…,n。假定Small John能提供一组信息:第i封信肯定不是装在信封j中。请编程帮助Small John,尽可能多地将信正确地装回信封。

     

    输入描述 Input Description

    n文件的第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。

    n接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。文件最后一行是2个0,表示结束。

    输出描述 Output Description

    输出文件的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。

    样例输入 Sample Input

    3

    1  2

    1  3

    2  1

    0  0

    样例输出 Sample Output

    1   1

    /*
    开始把边取反,然后跑一边匈牙利算法,然后判断是不是完美匹配(概念网上自己去找),不是就直接输出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;
        }
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    Flutter 容器(4)
    Linux 安装maven环境
    ajaxStart、ajaxStop使用注意事项
    jquery里用正则来验证密码,必须包含大小写字母,数字及特殊符号,或最少包含两种
    Nginx 相关介绍(Nginx是什么?能干嘛?配有图片示例)
    常见web攻击总结
    用php的chr和ord函数实现字符串和ASCII码互转
    消息队列设计精要
    mysql索引总结----mysql 索引类型以及创建
    MySQL事务隔离级别详解
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7324296.html
Copyright © 2020-2023  润新知