题意:投票,投票可以传递,当一个人投票时,要把此人的得票数全给被投的那个人,问最后按升序输出得票数最高的人。
想法:显然在一个连通块内的所有点的得票数都是一样的,即:块内点数-1,(1:是他自己本身)。所以先要tarjan缩点,然后求出每一个块可以由几个块到达(这里可以反向建边dfs)。最后输出最大得票数的人即可。
#include<iostream> #include<cstring> #include<cstdio> #include<stack> #include<algorithm> #define mm(x) memset(x,0,sizeof(x)) using namespace std; const int N=5000+50; const int M=30000+50; int n,m; int dfn[N],low[N],num[N],paint[N],instack[N],index,col; int val[N],vis[N],res[N],ind[N]; struct node { int v,next; }; struct QXX { int head[N],cnt; node e[M]; void Init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int a,int b) { e[cnt].v=b; e[cnt].next=head[a]; head[a]=cnt++; } }qxx1,qxx2; stack<int>s; void tarjan_Init() { index=col=0; mm(dfn); mm(low); mm(num); mm(paint); mm(instack); while(!s.empty()) s.pop(); } int Min(int a,int b) { if(a<b) return a; return b; } void tarjan(int u) { dfn[u]=low[u]=++index; instack[u]=1; s.push(u); for(int i=qxx1.head[u];i+1;i=qxx1.e[i].next) { int v=qxx1.e[i].v; if(!dfn[v]) { tarjan(v); low[u]=Min(low[u],low[v]); } else if(instack[v]) { low[u]=Min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { ++col; int k=s.top(); while(u!=k) { s.pop(); paint[k]=col; num[col]++; instack[k]=0; k=s.top(); } s.pop(); paint[u]=col; num[col]++; instack[u]=0; } } int dfs(int u,int &sum) { vis[u]=1; sum+=num[u]; for(int i=qxx2.head[u];i+1;i=qxx2.e[i].next) { int v=qxx2.e[i].v; if(vis[v]) continue; dfs(v,sum); } } int main() { int t,ca=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); tarjan_Init(); qxx1.Init(); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); qxx1.add(a,b); } for(int i=0;i<n;i++) { if(!dfn[i]) tarjan(i); } qxx2.Init(); mm(ind); for(int i=0;i<n;i++) { int a=paint[i]; for(int j=qxx1.head[i];j+1;j=qxx1.e[j].next) { int b=paint[qxx1.e[j].v]; if(a!=b) { qxx2.add(b,a); ind[a]++; } } } mm(val); for(int i=1;i<=col;i++) { if(ind[i]==0) { mm(vis); int sum=0; dfs(i,sum); val[i]=sum; } } int maxx=-1; for(int i=1;i<=col;i++) { if(val[i]>maxx) { maxx=val[i]; } } int num=0; for(int i=0;i<n;i++) { if(val[paint[i]]==maxx) { res[num++]=i; } } sort(res,res+num); printf("Case %d: %d\n",ca++,maxx-1); for(int i=0;i<num;i++) { if(i!=0) printf(" "); printf("%d",res[i]); } printf("\n"); } return 0; }
时间: 2024-11-02 19:50:05