特殊圖poj2367-Genealogical tree poj-1776Task Sequences BZOJ1006: [HNOI2008]神奇的國度

特殊圖poj2367-Genealogical tree poj-1776Task Sequences BZOJ1006: [HNOI2008]神奇的國度

分類:
樹:無環聯通圖
平面圖:邊沒交點
平面圖的對偶圖:平面圖網絡流轉化爲最短路
有向無環圖
二分圖
正則圖:任意倆頂點度數相同
弦圖:圖中任意長度大於3的環都含一條弦
競賽圖:任意兩點間有切僅有一條有向邊


算法:
拓撲排序
O(V+E)

Genealogical tree
Time Limit: 1000MS
Memory Limit: 65536K
Special Judge
Description
The system of Martians’ blood relations is confusing enough. Actually, Martians bud when they want and where they want. They gather together in different groups, so that a Martian can have one parent as well as ten. Nobody will be surprised by a hundred of children. Martians have got used to this and their style of life seems to them natural.
And in the Planetary Council the confusing genealogical system leads to some embarrassment. There meet the worthiest of Martians, and therefore in order to offend nobody in all of the discussions it is used first to give the floor to the old Martians, than to the younger ones and only than to the most young childless assessors. However, the maintenance of this order really is not a trivial task. Not always Martian knows all of his parents (and there’s nothing to tell about his grandparents!). But if by a mistake first speak a grandson and only than his young appearing great-grandfather, this is a real scandal.
Your task is to write a program, which would define once and for all, an order that would guarantee that every member of the Council takes the floor earlier than each of his descendants.
Input
The first line of the standard input contains an only number N, 1 <= N <= 100 — a number of members of the Martian Planetary Council. According to the centuries-old tradition members of the Council are enumerated with the natural numbers from 1 up to N. Further, there are exactly N lines, moreover, the I-th line contains a list of I-th member’s children. The list of children is a sequence of serial numbers of children in a arbitrary order separated by spaces. The list of children may be empty. The list (even if it is empty) ends with 0.
Output
The standard output should contain in its only line a sequence of speakers’ numbers, separated by spaces. If several sequences satisfy the conditions of the problem, you are to write to the standard output any of them. At least one such sequence always exists.
Sample Input
5
0
4 5 1 0
1 0
5 3 0
3 0
Sample Output
2 4 5 3 1
Source
Ural State University Internal Contest Octobe2000 Junior Session

題意:輸出一個拓撲序
流程:
(1)入度0的點入隊
(2)每次取出隊首的點
(3)連出的邊入度-1,重複(1)
(4)重複(2)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 200;

int n, map[MAXN][MAXN], in[MAXN];
queue<int> q;

void BFS(){
    for (int i = 1; i <= n; ++i)
      if (!in[i])
        q.push(i);
    while (!q.empty()) {
      int x = q.front();
      q.pop();
      cout<<x<<" ";
      for (int i = 1; i <= n; ++i) {
        if (!map[x][i]) continue;
        in[i]--;
        if (!in[i])
          q.push(i);
      }
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    cin>>n;
    for (int i = 1; i <= n; ++i) {
      int x; cin>>x;
      while (x) {
        map[i][x] = 1;
        in[x]++;
        cin>>x;
      }
    }
    BFS();
    return 0;
} 

Task Sequences
Time Limit: 1000MS
Memory Limit: 65536K
Special Judge
Description
Tom has received a lot of tasks from his boss, which are boring to deal with by hand. Fortunately,Tom got a special machine - Advanced Computing Machine (ACM) to help him.
ACM works in a really special way. The machine can finish one task in a short time, after it’s finishing one task, it should smoothly move to the next one, otherwise the machine will stop automatically. You must start it up again to make it continue working. Of course, the machine cannot move arbitrarily from one task to another. So each time before it starts up, one task sequence should be well scheduled. Specially, a single task also can be regarded as a sequence. In the sequence, the machine should be able to smoothly move from one task to its successor (if exists). After started up, the machine always works according to the task sequence, and stops automatically when it finishes the last one. If not all the tasks have been finished, the machine has to start up again and works according to a new sequence. Of course, the finished tasks can’t be scheduled again.
For some unknown reasons, it was guaranteed that for any two tasks i and j, the machine can smoothly move from i to j or from j to i or both. Because the startup process is quite slow, Tom would like to schedule the task sequences properly, so that all the tasks can be completed with minimal number of startup times. It is your task to help him achieve this goal.
Input
Input contains several testcases. For each testcase, the first line contains only one integer n, (0 < n <= 1,000), representing the number of tasks Tom has received. Then n lines follow. Each line contains n integers, 0 or 1, separated by white spaces. If the jth integer in the ith line is 1, then the machine can smoothly move from task i to task j, otherwise the machine can not smoothly move from task i to task j. The tasks are numbered from 1 to n.
Input is terminated by end of file.
Output
For each testcase, the first line of output is only one integer k, the minimal number of startup times needed. And 2k lines follow, to describe the k task sequences. For each task sequence, the first line should contain one integer m, representing the number of tasks in the sequence. And the second line should contain m integers, representing the order of the m tasks in the sequence. Two consecutive integers in the same line should be separated by just one white space. Extra spaces are not allowed. There may be several solutions, any appropriate one is accepted.
Sample Input
3
0 1 1
1 0 1
0 0 0
Sample Output
1
3
2 1 3
Source
Asia Guangzhou 2003

找哈密頓迴路:
(1)前提:競賽圖一定存在一條哈密頓路
(2)若競賽圖中,點集S = {v1……vi-1}爲首尾
相連的邊,對vi,一定有一種方法將它加入到S中

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1000 + 10;

int read(){
    int k = 1, x = 0; char ch = getchar();
    while (ch<'0'||ch>'9') { 
      if (ch == '-') k = -1;
      ch = getchar();
    }
    while ('0'<=ch && ch<='9') {
      x = x * 10 + ch - '0';
      ch = getchar();
    }
    return k * x;
}

int n, num[MAXN], head[MAXN], map[MAXN][MAXN], next[MAXN]; 

void solve(){
    int head = 1;
    num[head] = 1;
    next[head] = -1;
    for (int i = 2; i <= n; ++i) {
      num[i] = i;
      for (int j = head; j != -1; j = next[j]) {    
        if (j == head && map[i][num[j]]) {
          next[i] = head;
          head = i;
          break;
        }
        if (next[j] != -1 && map[num[j]][i] && map[i][num[next[j]]]) {
          next[i] = next[j];
          next[j] = i;
          break;
        }
        if (next[j] == -1) {
          next[i] = next[j];
          next[j] = i;
          break;
        }
      }
    }
    printf("1\n%d\n", n);
    printf("%d", head);
    for (int i = next[head]; i != -1; i = next[i]) {
      printf(" %d", num[i]);
    }
    printf("\n");
}

int main()
{
    freopen("in.txt", "r", stdin);
    while (scanf("%d", &n) != EOF) {
      memset(map, 0, sizeof map);
      for (int i = 1; i <= n; ++i) 
        for (int j = 1; j <= n; ++j)
          map[i][j] = read();;
      solve();
    }
    return 0;
}

1006: [HNOI2008]神奇的國度
Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 3998 Solved: 1851
[Submit][Status][Discuss]
Description
  K國是一個熱衷三角形的國度,連人的交往也只喜歡三角原則.他們認爲三角關係:即AB相互認識,BC相互認識,CA
相互認識,是簡潔高效的.爲了鞏固三角關係,K國禁止四邊關係,五邊關係等等的存在.所謂N邊關係,是指N個人 A1A2
…An之間僅存在N對認識關係:(A1A2)(A2A3)…(AnA1),而沒有其它認識關係.比如四邊關係指ABCD四個人 AB,BC,C
D,DA相互認識,而AC,BD不認識.全民比賽時,爲了防止做弊,規定任意一對相互認識的人不得在一隊,國王相知道,
最少可以分多少支隊。
Input
  第一行兩個整數N,M。1<=N<=10000,1<=M<=1000000.表示有N個人,M對認識關係. 接下來M行每行輸入一對朋

Output
  輸出一個整數,最少可以分多少隊
Sample Input
4 5
1 2
1 4
2 4
2 3
3 4
Sample Output
3
HINT
 一種方案(1,3)(2)(4)
Source

完美消除序列:O(V+E)
流程:
(1)對於每個下標i(從n開始倒序)
(2)Vi = V{V1…Vi-1}與{V1…Vi-1}
中相連最多的點
(3)對{Vi}倒敘貪心獲得染色方案
處理的難點在(2)
首先會想到用堆維護,時間複雜度爲O((V+E)logV)
實現:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int MAXN = 10000 + 10;

int read(){
    int k = 1, x = 0; char ch = getchar();
    while (ch<'0'||ch>'9') { 
      if (ch == '-') k = -1;
      ch = getchar();
    }
    while ('0'<=ch && ch<='9') {
      x = x * 10 + ch - '0';
      ch = getchar();
    }
    return k * x;
}

int n, m;
int vis[MAXN], cnt[MAXN], col[MAXN], used[MAXN], res[MAXN];
vector<int> map[MAXN];
//vector<int> bucket[MAXN];

int LCS(){
    priority_queue<pair<int, int> > q;
    for (int i = 1; i <= n; ++i)
      q.push(make_pair(0, i));
    for (int i = n; i >= 1; --i) {
        while (1) {
          int u = q.top().second;
          q.pop();
          if (vis[u]) continue;
          vis[u] = i;
          res[i] = u;
          for (vector<int> :: iterator iter = map[u].begin(); iter != map[u].end(); ++iter)
            if (!vis[*iter])
              q.push(make_pair(++cnt[*iter], *iter));
          break;
        }
    }
    int ans = 1;
    for (int j = n; j >= 1; --j) {
      int iter = res[j], can = 1;
      for (int i = 0; i < map[iter].size(); ++i)
        used[col[map[iter][i]]] = j;
      while (used[can] == j) can++;
      col[iter] = can;
      ans = max(ans, can);
    }   
    return ans;
}

int main()
{
    freopen("in.txt", "r", stdin);
    n = read(), m = read();
    for (int i = 1; i <= m; ++i) {
      int x = read(), y = read();
      map[x].push_back(y);
      map[y].push_back(x);
    }
    printf("%d", LCS());
    return 0;
}

用時1372 ms
看到有神犇180s搞定,於是想有沒有別的辦法。發現,只需要用個桶排序,與{V1…Vi}連的邊數作爲桶,維護桶的複雜度低於堆。
實現:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 10000 + 10;

int read(){
    int k = 1, x = 0; char ch = getchar();
    while (ch<'0'||ch>'9') { if (ch == '-') k = -1; ch = getchar(); }
    while ('0'<=ch && ch<='9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return k * x;
}

int n, m;
int vis[MAXN], cnt[MAXN], col[MAXN], res[MAXN], used[MAXN];
vector<int> map[MAXN];
vector<int> bucket[MAXN];

int get(){
    int top = 0;
    for (int i = 1; i <= n; ++i)
      bucket[0].push_back(i);
    for (int i = n; i >= 1; --i) {
        while (1) {
          //桶維護 
          if (!bucket[top].size()) top--;
          vector<int> :: iterator bri = bucket[top].end() - 1;
          bucket[top].erase(bri);
          int u = *bri;
          //得到完全消除序列的第i個 
          if (vis[u]) continue;
          vis[u] = i;
          res[i] = u;
          //更新不在序列裏的結點的cnt值 
          for (vector<int> :: iterator iter = map[u].begin(); iter != map[u].end(); ++iter)
            if (!vis[*iter]) {
              ++cnt[*iter];
              if (cnt[*iter] > top) top = cnt[*iter];
              bucket[cnt[*iter]].push_back(*iter);
            }
          break;
        }
    }
    int ans = 1;
    for (int j = n; j >= 1; --j) {
      int iter = res[j], can = 1;
      for (int i = 0; i < map[iter].size(); ++i)
        used[col[map[iter][i]]] = j;
      while (used[can] == j) can++;
      col[iter] = can;
      ans = max(ans, can);
    }   
    return ans;
}

int main()
{
    freopen("in.txt", "r", stdin);
    n = read(), m = read();
    for (int i = 1; i <= m; ++i) {
      int x = read(), y = read();
      map[x].push_back(y);
      map[y].push_back(x);
    }
    printf("%d", get());
    return 0;
}

用時656 ms。這說明,我離神犇差大約三個神犇的距離。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章