Harry and Magical Computer (HDU 5154)

Harry and Magical Computer

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 249    Accepted Submission(s): 118


Problem Description
In reward of being yearly outstanding magic student, Harry gets a magical computer. When the computer begins to deal with a process, it will work until the ending of the processes. One day the computer got n processes to deal with. We number the processes from 1 to n. However there are some dependencies between some processes. When there exists a dependencies (a, b), it means process b must be finished before process a. By knowing all the m dependencies, Harry wants to know if the computer can finish all the n processes.
 

Input
There are several test cases, you should process to the end of file.
For each test case, there are two numbers n m on the first line, indicates the number processes and the number of dependencies. 1n100,1m10000
The next following m lines, each line contains two numbers a b, indicates a dependencies (a, b). 1a,bn
 

Output
Output one line for each test case.
If the computer can finish all the process print "YES" (Without quotes).
Else print "NO" (Without quotes).
 

Sample Input
  
  
3 2 3 1 2 1 3 3 3 2 2 1 1 3
 

Sample Output
  
  
YES NO
 

Source
 
题意:
有一台电脑只能做一个任务直到结束才能做另外一个任务. 现有一种约束条件是(v,u) : 在做v任务前必须做u任务. 先在给你一个n和m
, n表示共有n个任务, m表示共有m个约束条件,问这台电脑是否能完成n个任务;

方法1:
 利用邻接矩阵建立一个有向图,看这个有向图是否会形成环. 用最短路floyd算法, 如果邻接矩阵的主对角线有1,则说明有环.

code_1:
/*************************************************************************
    > File Name: topo.cpp
    > Author: tj
    > Mail: 545061367@qq.com
    > Created Time: 2015年01月04日 星期日 11时01分24秒
 ************************************************************************/

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
	int n, m, u, v, dp[110][110];

	while(~scanf("%d%d", &n,&m))
	{
		memset(dp, 0, sizeof(dp));
		for(int i=1; i<=m; i++)
		{
			scanf("%d%d", &v,&u);
			dp[u][v] = 1;
		}
		for(int k=1; k<=n; k++)
			for(int i=1; i<=n; i++)
				for(int j=1; j<=n; j++)
					dp[i][j] = max(dp[i][j], dp[i][k]&dp[k][j]);
		int flag = 0;
		for(int i=1; i<=n; i++)
			if(dp[i][i] == 1) flag = 1;
		printf(!flag ? "YES\n" : "NO\n");
	}
	return 0;
}

方法二: (错了。。请忽略。。。)
利用类似并查集的方法,用p[v]数组来存储v的父亲,然后每次都要查询一下父亲的父类中是否会有等于儿子的情况. 如果有,则说明会形成环.


code_2:
/*************************************************************************
    > File Name: union-find.cpp
    > Author: tj
    > Mail: 545061367@qq.com
    > Created Time: 2015年01月04日 星期日 13时21分08秒
 ************************************************************************/

#include<stdio.h>
#include<iostream>
using namespace std;
int p[110];
bool find(int x, int val)
{
	if(p[x] == val) return 1; //如果x的父亲是val则存在环
	if(p[x] == x) return 0; //找到根结点就不用继续找了
	find(p[x], val); //继续查找父类
}

int main()
{
	int n, m, u, v;

	while(~scanf("%d%d", &n,&m))
	{
		for(int i=1; i<=n; i++) p[i] = i; //初始化父类
		int flag = 0;
		for(int i=1; i<=m; i++)
		{
			scanf("%d%d", &v,&u);
			if(find(u,v)) flag = 1; //如果查到v也是u的父类,则有环
			else p[v] = u; //u是v的父亲
		}
		printf(!flag ? "YES\n" : "NO\n");
	}
	return 0;
}
一个结点有可能有多个父结点,也就是说会指向多个点,这样并查集中那个点的指向会被覆盖,所以这样做是错误的,只是此题数据水让我过了。。
附测试数据:
4 4
2 3
3 1
3 4
1 2

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值