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

COJ 3012 LZJ的问题 (有向图判环)

时间:2015-04-21 22:01:10      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1042

试题描述:

LZJ有一个问题想问问大家。他在写函数时有时候很头疼,如他写了这样几个函数:

void f1()
{
   f2();
   f3();
}
void f2()
{
   f3();
}
void f3()
{
   f1();
}
LZJ发现他无论怎么调换函数的位置,编译器总是不能通过编译,因为编译器规定调用的函数必须在当前函数之前写。
还有一种情况是这样的:
void f4()
{
   f4();
}
虽然能通过编译但会无限递归。
现在LZJ想问问你,他写了一些函数,并且给你每个函数调用了哪些别的函数(可能调用本身),请问他能否通过调整函数的位置,使得编译器通过编译且不会出现无限递归?

输入:

输入第一行为一个正整数N,表示有N个函数。
接下来N行每第i行开始有一个自然数K,表示第i个函数共调用了多少别的函数(可能调用本身),接下来K个正整数vij,表示函数i调用了函数vij。

输出:

若可以输出“Yes”,否则输出“No”。

输入示例:

5
1 2
1 3
2 4 5
1 5
0

输出示例:

Yes

其他说明:

1<=N<=200,1<=K<=N, 1<=vij<=N

题解:裸有向图判环直接拓扑排序,然后如果作死可以把边搞成负的上Bellman_Ford……

然后记得判自环。

拓扑排序:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <queue>
 6 #define REP(s, n) for(int i = s; i <= n; i ++)
 7 using namespace std;
 8 const int maxn = 200 + 10;
 9 const int maxm = 80000 + 10;
10 int In[maxn], n, cnt = 0;
11 int first[maxn], next[maxm], to[maxm];
12 bool vis[maxn], TAT = true;
13 int ms = 1;
14 void AddEdge(int u, int v){
15     next[ms] = first[u];
16     first[u] = ms;
17     to[ms] = v;
18     In[v] ++; ms ++;
19     return ;
20 }
21 void read(int& x){
22     x = 0; int sig = 1; char ch = getchar();
23     while(!isdigit(ch)) { if(ch == -) sig = -1; ch = getchar(); }
24     while(isdigit(ch)) x = 10 * x + ch -0, ch = getchar();
25     x *= sig; return ;
26 }
27 queue<int> Q;
28 void init(){
29     read(n);
30     int temp;
31     REP(1, n){
32         read(cnt);
33         while(cnt --){
34             read(temp);
35             if(temp == i) { TAT = false; return ; }
36             AddEdge(i, temp);
37         }
38     }
39     return ;
40 }
41 void work(){
42     if(!TAT) return ;
43     REP(1, n) if(In[i] == 0) Q.push(i), vis[i] = true;
44     while(!Q.empty()){
45         int x = Q.front(); Q.pop();
46         for(int i = first[x]; i; i = next[i]){
47             int& v = to[i];
48             if(vis[v]) continue;
49             In[v] --;
50             if(In[v] == 0) Q.push(v), vis[v] = true;
51         }
52     }
53     return ;
54 }
55 void print(){
56     if(!TAT) { puts("No"); return ;}
57     REP(1, n) if(!vis[i]) { puts("No"); return ;}
58     puts("Yes"); return ;
59 }
60 int main(){
61     init();
62     work();
63     print();
64     return 0;
65 }

Bellman_Ford:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #define INF 1000000000
 6 using namespace std;
 7 const int maxn=200+10,maxm=80000+10;
 8 struct Tedge{int x,y,w,next;}adj[maxm];int ms=0,fch[maxn];
 9 void AddEdge(int u,int v){
10     adj[++ms]=(Tedge){u,v,-1,fch[u]};fch[u]=ms;return;
11 }
12 int d[maxn],n;
13 bool relax(int u,int v,int w){
14     if(d[v]>d[u]+w){d[v]=d[u]+w;return true;}
15     return false;
16 }
17 inline int read(){
18     int x=0,sig=1;char ch=getchar();
19     while(!isdigit(ch)){if(ch==-) sig=-1;ch=getchar();}
20     while(isdigit(ch)) x=10*x+ch-0,ch=getchar();
21     return x*=sig;
22 }
23 inline void write(int x){
24     if(x==0){putchar(0);return;}if(x<0) putchar(-),x=-x;
25     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
26     for(int i=len-1;i>=0;i--) putchar(buf[i]+0);return;
27 }
28 void init(){
29     
30 }
31 bool bellman_ford(){
32     n=read();
33     for(int i=1;i<=n;i++) d[i]=INF;
34     for(int i=1;i<=n;i++){
35         int k=read();
36         for(int j=0;j<k;j++){
37             int a=read();
38             if(i==a) return false;
39             AddEdge(i,a);
40         }
41     }
42     bool ToT;
43     for(int i=1;i<=n;i++){
44         ToT=false;
45         for(int i=1;i<=ms;i++){
46             int u=adj[i].x,v=adj[i].y,w=adj[i].w;
47             if(relax(u,v,w)) ToT=true;
48         }
49         if(!ToT) break;
50     }
51     for(int i=1;i<=ms;i++){
52         int u=adj[i].x,v=adj[i].y,w=adj[i].w;
53         if(relax(u,v,w)) return false;
54     }
55     return true;
56 }
57 void work(){
58     if(bellman_ford()) puts("Yes");
59     else puts("No");
60     return;
61 }
62 void print(){
63     return;
64 }
65 int main(){
66     init();work();print();return 0;
67 }
68 /*
69 5
70 1 1
71 1 3
72 1 4
73 1 5
74 1 6
75 */

 

COJ 3012 LZJ的问题 (有向图判环)

标签:

原文地址:http://www.cnblogs.com/chxer/p/4445438.html

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