hdu 6165 FFF at Valentine(tarjan缩点+拓扑排序)

FFF at Valentine

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 780    Accepted Submission(s): 387


Problem Description

At Valentine's eve, Shylock and Lucar were enjoying their time as any other couples. Suddenly, LSH, Boss of FFF Group caught both of them, and locked them into two separate cells of the jail randomly. But as the saying goes: There is always a way out , the lovers made a bet with LSH: if either of them can reach the cell of the other one, then LSH has to let them go.
The jail is formed of several cells and each cell has some special portals connect to a specific cell. One can be transported to the connected cell by the portal, but be transported back is impossible. There will not be a portal connecting a cell and itself, and since the cost of a portal is pretty expensive, LSH would not tolerate the fact that two portals connect exactly the same two cells.
As an enthusiastic person of the FFF group, YOU are quit curious about whether the lovers can survive or not. So you get a map of the jail and decide to figure it out.
 

Input
Input starts with an integer T (T≤120), denoting the number of test cases.

For each case,
First line is two number n and m, the total number of cells and portals in the jail.(2≤n≤1000,m≤6000)
Then next m lines each contains two integer u and v, which indicates a portal from u to v.
a
 

Output
If the couple can survive, print “I love you my love and our love save us!”
Otherwise, print “Light my fire!”
 

Sample Input
 
   
3 5 5 1 2 2 3 2 4 3 5 4 5 3 3 1 2 2 3 3 1 5 5 1 2 2 3 3 1 3 4 4 5
 

Sample Output
 
   
Light my fire! I love you my love and our love save us! I love you my love and our love save us!
 

tarjan算法详解(大神博客):http://www.cnblogs.com/uncle-lu/p/5876729.html
点击打开链接


题意:
问你一幅有向图中能不能从一个点出发,一次走完所有的点

解析:
用tarjan缩点,将图中的环都处理成点,再用拓扑排序,若一次入队列有>1个点,则说明不行,否则可以


#include
#include
#include
#include
#include
using namespace std;
#define MAXN 1010
#define MAXM 6010

typedef struct node
{
	int u,v;
	int next;
}node;

int n,m,cnt,index;
node edge[MAXM];
int head[MAXN],ufset[MAXN],indegree[MAXN];
int DFN[MAXN],LOW[MAXN],visit[MAXN];
stack ms;
vector gg[MAXN];

void addEdge(int u,int v)
{
	edge[cnt].next=head[u];
	edge[cnt].u=u;
	edge[cnt].v=v;
	head[u]=cnt++;
}

void tarjan(int x)
{
	DFN[x]=LOW[x]=++index;   
	ms.push(x);   
	visit[x]=1;   //标记入栈
	for(int i=head[x];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		if(!DFN[v])   //如果这条边没有遍历过
		{
			tarjan(v);  //递归遍历他
			LOW[x]=min(LOW[x],LOW[v]);   //并将x加入到根节点比它小(入栈时间比它早)的树中,若还是low[x]比较小,那么x自己就是一棵一个节点的树
		}
		else if(visit[v])   //如果这个点已经被遍历过且现在还在栈中,说明存在环
		{
			LOW[x]=min(LOW[x],DFN[v]);   //得到环的最开始的判定就是从这一步开始的,因为只通过LOW[x]=min(LOW[x],LOW[v]),只能从自己下面(即后搜的点中得到父节点信息)
			//LOW[x]=min(LOW[x],LOW[v]);
		}                                  //而当自己连接的那条边是构成环的那条边时,就是通过这一步得到的,将自己现在的父节点的入栈时间low[x]与在自己之前已经入栈(遍历过)且还在栈中的节点的入栈时间比较
	}
	if(DFN[x]==LOW[x])  //任何一个强连通分量,必定是对原图的深度优先搜索树的子树
	{
		int u;
		do
		{
			u=ms.top();
			ms.pop();
			ufset[u]=x;  //一个环添加到一个并查集中
			visit[u]=0;

		}while(u!=x);
	}
}


int toposort()
{
	queue mq;
	for(int i=1;i<=n;i++)
	{
		int b=ufset[i];
		if(indegree[b]==0&&visit[b]==0)
		{
			mq.push(b);
			visit[b]=1;
			if(mq.size()>1) return 0;
		}
	}

	while(mq.size())
	{
		int tmp=mq.front();
		mq.pop();
		int time=0;
		for(int i=0;i1) return 0;
			
		}
	}
	return 1;
}


int main()
{
	int t,a,b;
	scanf("%d",&t);
	while(t--)
	{
		memset(edge,0,sizeof(edge));
		memset(DFN,0,sizeof(DFN));
		memset(LOW,0,sizeof(LOW));
		memset(head,-1,sizeof(head));
		memset(ufset,-1,sizeof(ufset));

		cnt=index=0;
		scanf("%d%d",&n,&m);
		for(int i=0;i



你可能感兴趣的:(拓扑排序,2017多校,图论,tarjan)