UVALive 6432 In uence(枚举+dfs或记忆化搜索+bitset)

6432 In
uence
In any society there are social in
uence relations between individuals, where a person x can in
uence
another person y. The same is true for Softopia, a special society where social in
uence relations
are also transitive, meaning that if x can in
uence y and y can in
uence z, then x also in
uences z.
Moreover, the rules of social in
uence guarantee that if x in
uences any other person y, then x cannot
be in
uenced by y as well. Using these simple rules, if a person x from Softopia wants something, then
all the nodes in
uenced by x also want the same thing.
Although, Softopia is almost a perfect society, there is a set of certain individuals, X, that would
spread false demands through the social in
uence mechanism used by the society. And there is also an
evil entity that would want to nd out which of these people should be selected to spread a demand of
their own. Because the society can only select one person from X, it would like to select one that is
able to in
uence as many people as possible from Softopia. If there is more than a person that satis es
this request, you should pick the one with the lowest identi er.
Input
The input le contains several test cases, each of them as described below.
The input starts with a line containing two integers separated by one space: n (n 5000) the
number of individuals in the society, and k, the number of elements in set X. The next line contains
the elements from X, thus k di erent integers from 1 : : : n separated by one space. Then follow n lines
and each line i, 1 i n, contains rst the identi er of the current person followed by the identi ers of
the persons that can be directly in
uenced by person i, all of them separated by a space. The persons
are labeled from 1 to n. The total number of in
uences in a society is less than 250000. Additional
whitespaces in the input le should be skipped.
Output
For each test case, the result, representing the identi er of the person that satis es the conditions
mentioned above, will be written on a single line.
Hint: The table below describes two samples of input and output.
Sample Input
5 2
1 2
1 3 4
2 3 4
3 5
4 5
5
6 3
1 2 3
1 2
2 5
3 4 2
4 6
ACM-ICPC Live Archive: 6432 { In
uence 2/2
5
6
Sample Output
1

3

题意:n个人,如果第i个人能影响第j个人,那么第j人一定不能影响第i个人,并且影响关系可以传递,即i影响j,j影响k,那么i也影响k。要从一些人中选一个人,使得这个人的影响的人最多要。

题解:根据影响关系建图。

第一种方法:枚举选的人,然后dfs暴搜求一个人能影响的人的个数,因为每个点只会访问一次,所以dfs的复杂度为O(n),总复杂度为O(n^2)

第二种方法:记忆化搜索,用bitset<5001>dp[i],表示第i个人能影响到人。复杂度(O(n*n/64))。

第一种方法代码如下:

#include<cstring>
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#define nn 5100
using namespace std;
int n,k;
int a[5100];
char s[1100000];
struct node
{
    int st,en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en)
{
    E[num].en=en;
    E[num].next=p[st];
    p[st]=num++;
}
int zhuan(string x)
{
    int lx=x.size();
    int re=0;
    int po=1;
    for(int i=lx-1;i>=0;i--)
    {
        re+=po*(x[i]-'0');
        po*=10;
    }
    return re;
}
bool vis[5100];
int dfs(int id)
{
    vis[id]=true;
    int re=1;
    int i,w;
    for(i=p[id];i+1;i=E[i].next)
    {
        w=E[i].en;
        if(!vis[w])
        {
            re+=dfs(w);
        }
    }
    return re;
}
int main()
{
    int i,j,ls;
    string ix;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=1;i<=k;i++)
        {
            scanf("%d",&a[i]);
        }
        init();
        getchar();
        for(i=1;i<=n;i++)
        {
            gets(s);
            ls=strlen(s);
            ix="";
            for(j=0;j<ls;j++)
            {
                if(s[j]==' ')
                {
                    if(ix.size())
                    {
                        int fc=zhuan(ix);
                        if(fc!=i)
                        {
                            add(i,fc);
                        }
                    }
                    ix="";
                }
                else
                    ix+=s[j];
            }
            if(ix.size())
            {
                int fc=zhuan(ix);
                if(fc!=i)
                {
                    add(i,fc);
                }
            }
        }
        int ans=0;
        int id;
        for(i=1;i<=k;i++)
        {
            for(j=0;j<=n;j++)
                vis[j]=false;
            int fc=dfs(a[i]);
            if(fc>ans)
            {
                ans=fc;
                id=a[i];
            }
            else if(fc==ans)
                id=min(id,a[i]);
        }
        printf("%d\n",id);
    }
    return 0;
}

第二种方法代码如下:

#include<cstring>
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#include<bitset>
#define nn 5100
using namespace std;
int n,k;
int a[5100];
char s[1100000];
struct node
{
    int st,en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en)
{
    E[num].en=en;
    E[num].next=p[st];
    p[st]=num++;
}
int zhuan(string x)
{
    int lx=x.size();
    int re=0;
    int po=1;
    for(int i=lx-1;i>=0;i--)
    {
        re+=po*(x[i]-'0');
        po*=10;
    }
    return re;
}
bitset<5001>dp[nn];
void dfs(int id)
{
    dp[id].set(id);
    int i,w;
    for(i=p[id];i+1;i=E[i].next)
    {
        w=E[i].en;
        if(dp[w].none())
        {
            dfs(w);
        }
        dp[id]=dp[id]|dp[w];
    }
}
int main()
{
    int i,j,ls;
    string ix;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=1;i<=k;i++)
        {
            scanf("%d",&a[i]);
        }
        init();
        getchar();
        for(i=1;i<=n;i++)
        {
            gets(s);
            ls=strlen(s);
            ix="";
            for(j=0;j<ls;j++)
            {
                if(s[j]==' ')
                {
                    if(ix.size())
                    {
                        int fc=zhuan(ix);
                        if(fc!=i)
                        {
                            add(i,fc);
                        }
                    }
                    ix="";
                }
                else
                    ix+=s[j];
            }
            if(ix.size())
            {
                int fc=zhuan(ix);
                if(fc!=i)
                {
                    add(i,fc);
                }
            }
        }
        for(i=1;i<=n;i++)
            dp[i].reset();
        for(i=1;i<=n;i++)
        {
            if(dp[i].none())
            {
                dfs(i);
            }
        }
        int ans=0;
        int id=-1;
        for(i=1;i<=k;i++)
        {
            if((int)dp[a[i]].count()>ans)
            {
                ans=dp[a[i]].count();
                id=a[i];
            }
            else if((int)dp[a[i]].count()==ans)
                id=min(id,a[i]);
        }
        printf("%d\n",id);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值