zoukankan      html  css  js  c++  java
  • hdu 3639 有向图缩点+建反向图+搜索

    题意:给个有向图,每个人可以投票(可以投很多人,一次一票),但是一个人只能支持一人一次,支持可以传递,自己支持自己不算,被投支持最多的人。

    开始想到缩点,然后搜索,问题是有一点想错了!以为支持按票数计算,而不是按人数!还各种树形dp/搜索求可以到达边数。。提交WA了。。。

    又反复读了题目之后才发现。。错误。。只要人数就行。。。问题简单了许多。。。

    缩点成有向无环图后:每个SCC中支持的人数就是scc里面的人,要求可到达的点最多的点,当然要放过来求方便:反向图那个点可以到达的点最多!于是建反向图直接dfs即可,记录答案有点麻烦。。。提交就A了。。。这题总体花了我2多个小时。。算失败。。。

    #include<iostream>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int maxv=5005,maxe=50005;
    int nume=0;int head[maxv];int e[maxe][3];
    void inline adde(int i,int j,int c)
    {
        e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
        e[nume++][2]=c;
    }
    int dfn[maxv];int low[maxv];int vis[maxv];int ins[maxv]; stack<int>sta;
    int scc[maxv];int numb=0;int times=0;
    int n,m;  int sccsize[maxv];
    void tarjan(int u)
    {
        dfn[u]=low[u]=times++;
        ins[u]=1;
        sta.push(u);
        for(int i=head[u];i!=-1;i=e[i][1])
        {
            int v=e[i][0];
            if(!vis[v])
            {
                vis[v]=1;
                tarjan(v);
                if(low[v]<low[u])low[u]=low[v];
            }
            else if(ins[v]&&dfn[v]<low[u])
            {
                low[u]=dfn[v];
            }
        }
        if(low[u]==dfn[u])
        {
            numb++;int counted=0;
            int cur;
           do
            {
                cur=sta.top();
                sta.pop();
                ins[cur]=0;
                scc[cur]=numb;
                counted++;
            }while(cur!=u);
            sccsize[numb]=counted;
        }
    }
    struct pi
    {
        int id;
        int w;
    };
    bool my (pi a,pi b)
    {
        if(a.w!=b.w)
          return a.w>b.w;
        else
          return a.id<b.id;
    }
    int sums=0;
    vector<vector<int> >e2(maxv+1);
    int ind[maxv];
    void dfs(int u)
    {
        for(int i=0;i<e2[u].size();i++)
        {
            int v=e2[u][i];
            if(!vis[v])
            {
                vis[v]=1;
                sums+=sccsize[v];
                dfs(v);
            }
        }
    }
    vector<int>sumss;
    void solve()
    {
        for(int i=0;i<n;i++)
       {
           if(!vis[i])
           {
               vis[i]=1;
               tarjan(i);
           }
       }
        for(int i=0;i<n;i++)
          for(int j=head[i];j!=-1;j=e[j][1])
          {
              int v=e[j][0];
              if(scc[i]!=scc[v])
             {
                e2[scc[v]].push_back(scc[i]);
                ind[scc[i]]++;
             }
          }
          int minsums=0;
          vector<pi>ans;
        for(int i=1;i<=numb;i++)
            {
                sums=0;
                memset(vis,0,sizeof(vis));
                if(ind[i]==0)
                {
                    vis[i]=1;
                    sums+=sccsize[i]-1;
                    dfs(i);
                  if(sums>=minsums)
                  {
                      pi tp;
                      tp.w=sums;
                      tp.id=i;
                      ans.push_back(tp);
                      minsums=sums;
                  }
                }
            }
            vector<int>realans;
           for(int i=0;i<ans.size();i++)
            {
                if(ans[i].w==minsums)
                {
                    realans.push_back(ans[i].id);
                }
            }
        for(int j=0;j<realans.size();j++)
            for(int i=0;i<n;i++)
            {
                if(scc[i]==realans[j])
                {
                    sumss.push_back(i);
                }
            }
         sort(sumss.begin(),sumss.end());
         printf("%d
    ",minsums);
         for(int i=0;i<sumss.size();i++)
         {
              if(i!=sumss.size()-1)
                  printf("%d ",sumss[i]);
              else
                   printf("%d
    ",sumss[i]);
         }
    }
    void read_build()
    {
        int aa,bb,cc;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&aa,&bb);
            adde(aa,bb,0);
        }
    }
    void init()
    {
        numb=times=nume=0;
        sumss.clear();
        for(int i=0;i<maxv;i++)
          {
              head[i]=-1;
              ins[i]=dfn[i]=low[i]=scc[i]=vis[i]=0;
              sccsize[i]=0;
              ind[i]=0;
              e2[i].clear();
          }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        int ct=1;
        while(T--)
        {
            scanf("%d%d",&n,&m);
            init();
            read_build();
            printf("Case %d: ",ct++);
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    验证码破解 | Selenium模拟登陆12306
    验证码破解 | Selenium模拟登录知乎
    Numpy | 16 算术函数
    Numpy | 15 数学函数
    Numpy | 14 字符串函数
    Numpy | 13 位运算
    Numpy | 12 数组操作
    Numpy | 11 迭代数组
    Numpy | 10 广播(Broadcast)
    Numpy | 09 高级索引
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925691.html
Copyright © 2011-2022 走看看