【百度之星】度度熊与排列【暴力+二分图匹配】

题意:中文题,题意很好懂。要求每两个字符串重排以后编号要一样,可能有多种情况,就找字典序就小的。

题解:一开始有点懵,然后发现要找的序列要满足所以字符串,不知所措。然后想到了那么多人过了,肯定暴力啊。然后就暴力二分图匹配,找到满足情况的i,j匹配起来。然后跑一个匈牙利,倒着跑(字典序最小)。然后就能得到结果啦。注意跑完以后还要看看匹配数量和link的值哦。

#pragma comment(linker, "/STACK:102400000,102400000")
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
map<long long,bool> M;
const long long mod=1234577;
const int maxn=1e6+10;
ll gcd(ll x, ll y) {if (y == 0) return x; else return gcd(y, x % y); }
const double eps=1e-8;
int k;
int g[600][600];
int link[600];
bool used[500];
int n,m;
bool dfs(int u)
{
    int v;
    for(v=1;v<=m;v++)
        if(g[u][v]&&!used[v])
        {
            used[v]=true;
            if(link[v]==-1||dfs(link[v]))
            {
                link[v]=u;
                return true;
            }
        }
    return false;
}

int hungary()

{
    int res=0;
    int u;
    memset(link,-1,sizeof(link));
    for(u=m;u>=1;u--)
    {
        memset(used,0,sizeof(used));
        if(dfs(u)) res++;
    }
    return res;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        mm(g,0);
        string N[25];
        scanf("%d %d",&n,&m);
        char s1[30][55],s2[30][55];
        for(int c=0;c<n;c++)
        {
            scanf("%s",s1[c]);
            scanf("%s",s2[c]);
        }
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<m;j++)
            {
                int flag=1;
                for(int k=0;k<n;k++)
                {
                    if(s1[k][i]!=s2[k][j])
                    {
                        flag=0;
                        break;
                    }
                }
                if(flag) g[j+1][i+1]=1;
            }
        }
        int ans=hungary();
        //printf("%d
",ans);
        int flag=1;
        for(int i=1;i<=m;i++)
        {
            if(link[i]==-1)
            {
                flag=0;
                break;
            }
        }
        if(!flag)
        {
            printf("-1
");
            continue;
        }

        for(int i=1;i<=m;i++)
        {
            printf("%d",link[i]);
            if(i!=m) printf(" ");
        }
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Tangent-1231/p/11375346.html