码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3639 Hawk-and-Chicken tarjan缩点+dfs

时间:2016-05-07 11:12:46      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

题意:投票,投票可以传递,当一个人投票时,要把此人的得票数全给被投的那个人,问最后按升序输出得票数最高的人。


想法:显然在一个连通块内的所有点的得票数都是一样的,即:块内点数-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;
}

HDU 3639 Hawk-and-Chicken tarjan缩点+dfs

标签:

原文地址:http://blog.csdn.net/triple_wdf/article/details/51334368

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!