分隊長選挙

タイトル:クラスリーダー選挙
トピック:
大学生クラスクラスリーダー、N人の学生は自分の意見を表明できます。
意見がABの場合、AはBが適切であると考え、推移的です。 Cが適しています。
勤勉なTTはMの意見を収集し、最大投票数を知りたいと思っています。候補者のリスト、つまり最も投票数の多いすべての学生を教えてくれますか?

入力:
この質問には複数のデータセットがあります。最初の行Tは、データグループの数を表します。データの各セットは2つの整数NとM(2 <= n <= 5000、0 <m <= 30000)で始まり、2つの整数AとBを含むM行があります(A!= B)は、AがBと考えることを意味します適切です。

出力:
データの各セットについて、最初の行は "Case x:"を出力します。xは、1から始まるデータの数を示し、その後に最大数の投票が続きます。
次の行は、投票数が最も多い学生の数をスペースで区切って出力し、行末のスペースは無視しません!

サンプル:
ここに画像の説明を挿入

問題解決のアイデア:この問題は、学生をポイントとして扱い、a-> b投票をエッジ構成として扱うことができます。次に、sccを介して強い関連コンポーネントを見つけます。各コンポーネントの各ポイントの値は、ポイントの数-1です。その後、ポイントが短縮され、各強い連結成分がポイントになります(収縮ポイントも逆のシーケンス図の後で)。a-> bがある場合、b +の各ポイントの投票数+ = aのポイント数一度だけ使用できます)、この時点で、グラフ全体を0度のポイントで実行し、最大のものを必要とするものを見つけて、収縮ポイントの中点をリストできます。

コード:

#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
int n,m;
vector<int> g[5005],g1[5005],g0[5005];
int in[5005],out[5005],d[5005],f[5005],dcnt=0,tcnt=0,vis[5005],ans[5005],maxn=0,jilu[5005];
void dfs(int x)//scc正逆图各跑一遍
{
    vis[x]=1;
    for(int i=0;i<g[x].size();i++)
    {
        if(!vis[g[x][i]])
        {
            dfs(g[x][i]);
        }
    }
    d[++dcnt]=x;
}
void dfs1(int x)
{
    f[x]=tcnt;
    for(int i=0;i<g0[x].size();i++)
    {
        if(!f[g0[x][i]])
        {
            dfs1(g0[x][i]);
        }
    }
}
void dfs2(int x,int y)//从入度为0的点开始跑
{
    vis[x]=1;
    for(int i=0;i<g1[x].size();i++)
    {
        int to=g1[x][i];
        if(!vis[to])
        {
            jilu[y]+=(jilu[to]+1);//加上,这里y是入度为0的点,所以修改它的票数不影响结果
            dfs2(to,y);
        }
    }
}
void suodian()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<g0[i].size();j++)
        {
            if(f[i]!=f[g0[i][j]])//缩点,逆序图
            {
                g1[f[i]].push_back(f[g0[i][j]]);
                in[f[g0[i][j]]]++;
            }
        }
    }
}
void sousuo()//搜索入度为0的点之后dfs
{
    for(int i=1;i<=tcnt;i++)
    {
        if(in[i]==0)
        {
            memset(vis,0,sizeof(vis));
            dfs2(i,i);
        }
    }
}
int main()
{
    int p;
    scanf("%d",&p);
    int s=0;
    while(p--)
    {
        s++;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(d,0,sizeof(d));
        memset(f,0,sizeof(f));
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        memset(jilu,0,sizeof(jilu));
        dcnt=tcnt=maxn=0;
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
        {
            g[i].clear();
            g1[i].clear();
            g0[i].clear();
        }
        int x,y;
        for(int i=0;i<m;i++)//正逆图
        {
            scanf("%d%d",&x,&y);
            g[x].push_back(y);
            g0[y].push_back(x);
        }
        for(int i=0;i<n;i++)
        {
            if(!vis[i])
            {
                dfs(i);
            }
        }
        for(int i=n;i>=1;i--)
        {
            if(!f[d[i]])
            {
                tcnt++;
                dfs1(d[i]);
            }
        }
        for(int i=0;i<n;i++)//初始化
        {
            jilu[f[i]]++;
        }
        for(int i=1;i<=tcnt;i++)
        {
            jilu[i]--;
        }
        suodian();
        sousuo();
        for(int i=1;i<=tcnt;i++)//找最大的那个
        {
            maxn=max(maxn,jilu[i]);
        }
        printf("Case %d: %d\n",s,maxn);
        int ff=0;
        for(int i=0;i<n;i++)//扫一遍
        {
            if(jilu[f[i]]==maxn)
            {
                if(ff==0)
                {
                    ff=1;
                }else
                {
                    printf(" ");
                }
                printf("%d",i);
            }
        }
        printf("\n");
    }
}
/*
8
8 11
0 1
1 2
2 0
2 7
6 2
6 7
3 0
3 6
4 3
6 5
5 4
*/
PGZ
元の記事を34件公開しました 賞賛されました0 訪問859

おすすめ

転載: blog.csdn.net/qq_43653717/article/details/105498655