zoukankan      html  css  js  c++  java
  • UESTC 898 方老师和缘分 --二分图匹配+强连通分量

    这题原来以为是某种匹配问题,后来好像说是强连通的问题。

    做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u->i。这样求出所有的强连通分量,每个强连通分量中方老师和缘分的数目一定是相等的,所以每个方老师一定可以找到与他在同一个强连通分量里的缘分,因为强连通分量中每个点都是可达的,某个方老师找到了其强连通分量中的非原配点,则该原配缘分一定可以在强连通分量中找到"新欢"。可以画个图看看。

    由于要构造非二分图,缘分的编号从n+1开始,到2n。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #define Mod 1000000007
    using namespace std;
    #define N 200007
    
    std::vector<int> G[4005];
    int low[4005],dfn[4005];
    int instk[4005],bel[4005];
    int n,Time,cnt,res;
    stack<int> stk;
    int ans[2005];
    
    
    void Tarjan(int u)
    {
        low[u] = dfn[u] = ++Time;
        stk.push(u);
        instk[u] = 1;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if(!dfn[v])
            {
                Tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(instk[v])
                low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u])
        {
            cnt++;
            int v;
            do
            {
                v = stk.top();
                stk.pop();
                instk[v] = 0;
                bel[v] = cnt;
            }while(u != v);
        }
    }
    
    void init()
    {
        memset(G,0,sizeof(G));
        memset(instk,0,sizeof(instk));
        memset(bel,-1,sizeof(bel));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        Time = cnt = 0;
        while(!stk.empty())
            stk.pop();
    }
    
    int main()
    {
        int i,j,u,v,k;
        while(scanf("%d",&n)!=EOF)
        {
            init();
            for(i=1;i<=n;i++)
            {
                scanf("%d",&k);
                while(k--)
                {
                    scanf("%d",&v);
                    G[i].push_back(v+n);
                }
            }
            for(i=1;i<=n;i++)
            {
                scanf("%d",&v);
                G[v+n].push_back(i);
            }
            for(i=1;i<=n;i++)
            {
                if(!dfn[i])
                    Tarjan(i);
            }
            for(u=1;u<=n;u++)
            {
                k = 0;
                for(i=0;i<G[u].size();i++)
                {
                    v = G[u][i];
                    if(bel[u] == bel[v])
                        ans[k++] = v-n;
                }
                sort(ans,ans+k);
                printf("%d",k);
                for(i=0;i<k;i++)
                    printf(" %d",ans[i]);
                printf("
    ");
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    损失函数
    DPM 目标检测1
    编程题
    枚举型和元类
    python 多继承
    网络基础Cisco路由交换一
    网络基础tcp/ip协议五
    网络基础tcp/ip协议四
    网络基础tcp/ip协议三
    网络基础tcp/ip协议二
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3765621.html
Copyright © 2011-2022 走看看