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. 1≤n≤100,1≤m≤10000
The next following m lines, each line contains two numbers a b, indicates a dependencies (a, b). 1≤a,b≤n
For each test case, there are two numbers n m on the first line, indicates the number processes and the number of dependencies. 1≤n≤100,1≤m≤10000
The next following m lines, each line contains two numbers a b, indicates a dependencies (a, b). 1≤a,b≤n
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).
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
2 3
3 1
3 4
1 2