Harry and Magical Computer (HDU 5154)

来源:互联网 发布:殖民地知乎 编辑:程序博客网 时间:2024/04/29 04:25

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 23 12 13 33 22 11 3
 

Sample Output
YESNO
 

Source
BestCoder Round #25
 
题意:
有一台电脑只能做一个任务直到结束才能做另外一个任务. 现有一种约束条件是(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

0 0