【Baltic 2001远程通信】

【题目描述】

波罗的海上有两个小岛:BornholmGotland。在每个小岛上都有一些神奇的远程通信端口,每个通信端口可以运行在两种模式下——发送模式和接收模式。BornholmGotland分别有nm个这样的端口,每个端口都连接着另一个小岛某个端口,称为“目标端口”。

请设置这n+m个端口的模式,使得所有端口都处于工作状态,即:

对于处于接收模式的端口A,另一个小岛上至少有一个以A为目标端口的端口被设置成发送模式。

对于处于发送模式的端口B,它的目标端口必须处于接收状态。

其中1n , m50000

如下图(每个点指向的点表示它的目标端口):

那么它的一种设置方案为:

Bornholm岛上1号、4号端口与Gotland岛上2号、5号端口被设置为接收状态,其他端口被设置为发送状态。

【题目解析】

 首先假设B岛的所有端口都设置为发送状态,将G岛的所有端口都设置为接受状态。这样的话,对于所有入度为0的G岛是无用状态,将G岛的这些端口的状态改为发送状态,然后将其对应的B岛的目标端口设置为接受状态,然后更新B岛所连接的G岛目标端口的入度,将新产生的入度为0的G岛的端口作为下一个用于更新的点。

【代码如下】

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <queue>
 4 
 5 using namespace std;
 6 
 7 const int Maxn = 100001;
 8 
 9 struct edge
10 {
11     int v;
12     edge* next;
13     edge(int _v ,edge* _next) : v(_v), next(_next) {}
14 }* E[Maxn];
15 
16 bool Sta[Maxn];
17 int N, M, Deg[Maxn];
18 queue <int> Q;
19 
20 void Print()
21 {
22     for (int i = 1; i <= N + M; ++i)
23         if (Sta[i]) cout << i << " OUT" << endl;
24         else cout << i << " IN" << endl;
25 }
26 
27 void Solve()
28 {
29     for (int i = N + 1; i <= N + M; ++i)
30         if (!Deg[i]) Q.push(i);
31     while (Q.size())
32     {
33         int i = Q.front(); Q.pop();
34         Sta[i] = true;
35         for (edge* j = E[i]; j; j = j -> next)
36         {
37             int v = j -> v;
38             if (!Sta[v]) continue;
39             Sta[v] = false;
40             for (edge* k = E[v]; k; k = k -> next)
41             {
42                 Deg[k -> v]--;
43                 if (!Deg[k -> v]) Q.push(k -> v);
44             }
45         }
46     }
47 }
48 
49 inline void edgeAdd(int x, int y)
50 {
51     E[x] = new edge(y, E[x]);
52 }
53 
54 void Init()
55 {
56     cin >> N >> M;
57     for (int i = 1; i <= N; ++i) Sta[i] = true;
58     int x, y;
59     while (cin >> x >> y) edgeAdd(x, y), Deg[y]++;
60 }
61 
62 int main()
63 {
64     freopen("test.in", "r", stdin);
65     Init();
66     Solve();
67     Print();
68     return 0;
69 }
原文地址:https://www.cnblogs.com/GXZC/p/2873159.html