HDU 6029 Graph Theory

Little Q loves playing with different kinds of graphs very much. One day he thought about an interesting category of graphs called ”Cool Graph”, which are generated in the following way:
Let the set of vertices be {1, 2, 3, …, n}. You have to consider every vertice from left to right (i.e. from vertice 2 to n). At vertice i, you must make one of the following two decisions:
(1) Add edges between this vertex and all the previous vertices (i.e. from vertex 1 to i−1).
(2) Not add any edge between this vertex and any of the previous vertices.
In the mathematical discipline of graph theory, a matching in a graph is a set of edges without common vertices. A perfect matching is a matching that each vertice is covered by an edge in the set.
Now Little Q is interested in checking whether a ”Cool Graph” has perfect matching. Please write a program to help him.

题意

给定图的 n 个顶点以及 a2,a3,...,an 。其中 ai(1ai2) 表示其在图中与其它点的关系:

  1. 点 i 与所有标号小于 i 的点均存在一条边。
  2. 点 i 与所有标号小于 i 的点都不存在边。

perfect matching 被定义为图中存在一个边集,使得所有顶点有且仅有一条边与之相连。

问对于给定的图,是否存在 perfect matching

解题思路

首先,由于每个点有且只有一条边相连,故要使得 perfect matching 存在,则 n 一定是偶数。

对于点 i :

  • ai=1 ,则存在 i1+Σnj=i+1(aj==1?1:0) 条边与之相连,必然在其中选择一条。
  • ai=2 ,则仅存在 Σnj=i+1(aj==1?1:0) 条边与之相连。

故从上述分析来看,若已经处理了所有 ai=2 的点 i 的边的情况,则剩下的所有 ai=1 的点必然能够两两组合。

考虑贪心的做法,从 1 ~ n,若 ai=2 ,则找到最小的满足 aj=1 j>i 的点 j ,取边 (i, j) 。当然,此做法可以等价的看作对于任意第 i 号点,一定满足 [i, n] 中 a[i]=2 的个数 <= [i, n] 中 a[i]=1 的个数

代码

#include
using namespace std;
int n, a[100010];
bool jug() {
    if(n%2) return false;
    int c[3] = {0, 0, 0};
    for(int i=n;i;i--) {
        c[ a[i] ]++;
        if(c[2] > c[1]) return false;
    }
    return true;
}
int main()
{
    int T;
    scanf("%d",&T);
    a[1] = 2;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
            scanf("%d",&a[i]);
        printf("%s\n", jug()?"Yes":"No");
    }
}

你可能感兴趣的:(HDU)