hdu3639 强连通+缩点 tarjan算法

来源:互联网 发布:python win32api 截屏 编辑:程序博客网 时间:2024/05/01 02:18

http://acm.split.hdu.edu.cn/showproblem.php?pid=3639
题意:投票:如果A投给B,B投给C,那么C也会得到A的投票。现在要求谁的票最多,并输出这些人的编号。
题解:跑tarjan求强连通分量,在强连通分量的队伍中,每个点都是相互投票的。那么对原图进行缩点,然后反向建图。选出入度为0的队伍进行dfs,求出有队伍投给了这个队伍。将总人数求和减去自己即可。最后输出在这个队伍的人的编号。
代码:

#include<set>#include<map>#include<queue>#include<vector>#include<string>#include<bitset>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>#include<ctime>#include<iomanip>#include<iostream>#define debug cout<<"aaa"<<endl#define d(a) cout<<a<<endl#define mem(a,b) memset(a,b,sizeof(a))#define LL long long#define lson l,mid,root<<1#define rson mid+1,r,root<<1|1#define MIN_INT (-2147483647-1)#define MAX_INT 2147483647#define MAX_LL 9223372036854775807i64#define MIN_LL (-9223372036854775807i64-1)using namespace std;const int N = 100000 + 5;const int mod = 1000000000 + 7;const double eps = 1e-8;int n,m,x[N],y[N];int head[N],len;int dfn[N],low[N],dfs_num;//dfn表示遍历深度,low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号int color[N],col_num,num[N];//染色 int stack[N],vis[N],top;//栈和栈指针int in[N],sum[N],cas=0;struct EdgeNode{    int to,next;}edge[N];void add(int i,int j){    edge[len].to=j;    edge[len].next=head[i];    head[i]=len++;} void init(){    mem(dfn,0),mem(low,0),mem(head,-1),len=top=col_num=dfs_num=0;}void tarjan(int x){    dfn[x]=low[x]=++dfs_num;    vis[x]=1;    stack[++top]=x;    for(int i=head[x];i!=-1;i=edge[i].next){        int temp=edge[i].to;        if(!dfn[temp]){            tarjan(temp);            low[x]=min(low[x],low[temp]);        }        else if(vis[temp]){            low[x]=min(dfn[temp],low[x]);        }    }     if(dfn[x]==low[x]){//构成强连通分量         vis[x]=0;        //染色         color[x]=++col_num;         num[col_num]=1;        while(stack[top]!=x){//退栈             color[stack[top]]=col_num;            num[col_num]++;            vis[stack[top]]=0;            top--;         }        top--;    }}int dfs(int u){    vis[u]=1;    int temp=num[u];    for(int k=head[u];k!=-1;k=edge[k].next){        int v=edge[k].to;        if(!vis[v]){            temp+=dfs(v);        }    }    return temp;}void solve(){    for(int i=0;i<n;i++){        if(!dfn[i]){            tarjan(i);        }    }    mem(head,-1),mem(in,0),mem(sum,0),len=0;    for(int i=1;i<=m;i++){        if(color[x[i]]!=color[y[i]]){            add(color[y[i]],color[x[i]]);            in[color[x[i]]]++;        }    }    int ans=-1;    for(int i=1;i<=col_num;i++){        if(in[i]==0){            mem(vis,0);            //记录得票数             sum[i]+=dfs(i);            ans=max(ans,sum[i]);        }    }    printf("Case %d: %d\n",++cas,ans-1);    bool flag=1;    for(int i=0;i<n;i++){         if(sum[color[i]]==ans){            if(flag){                printf("%d",i);                flag=0;            }            else{                printf(" %d",i);            }        }    }    puts("");}int main(){    int t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        init();        for(int i=1;i<=m;i++){            scanf("%d%d",&x[i],&y[i]);            add(x[i],y[i]);        }        solve();    }    return 0;}
阅读全文
0 0
原创粉丝点击