HDU 6029 Graph Theory

Graph Theory

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1520    Accepted Submission(s): 642


Problem Description
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  i1).
(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.
 

Input
The first line of the input contains an integer  T(1T50), denoting the number of test cases.
In each test case, there is an integer  n(2n100000) in the first line, denoting the number of vertices of the graph.
The following line contains  n1 integers  a2,a3,...,an(1ai2), denoting the decision on each vertice.
 

Output
For each test case, output a string in the first line. If the graph has perfect matching, output ''Yes'', otherwise output ''No''.
 

Sample Input
 
  
3
2
1
2
2
4
1 1 2
 

Sample Output
 
  
Yes
No
No
 

Source
题意:输入n,表示有n个点(编号从1~n),对第2~n每个点都做且仅做一种处理(处理1:把这个点同这个点之前的每个点之间都加一条线;处理2:这个点不予任何点相连)。等处理完所有点之后问有没有符合完美图的。完美图的定义是存在子图,组图中的点两两配对,且没有单独存在的点。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,order;
        cin>>n;
        int flag=-1,sum=0;
        for(int i=2;i<=n;i++)
        {
            cin>>order;
            if(order==1)
            {
                if(sum<i-1)
                sum+=2;
            }///如果当前第i个点的操作是1,且当前加入集合sum的点的个数小于i-1,则加入第i-1个点和第i个点(i-1与i配对入集合sum)
        }
        if(n%2==1)printf("No\n");///奇数点一定存在被孤立的点,一定不符合
        else
        {
            if(sum==n) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}
方法二:记录其中孤立的点,当n为偶数且孤立的点个数为0时输出yes。(此法总体耗时较少)
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,order;
        scanf("%d",&n);
        int sum=1;///表示单独存在的点的个数
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&order);
            if(order==1)///当对当前点i的操作为1,则会减去一个当前孤立的点,一同这个点i入集合
                sum--;
            else sum++;///当对i的操作为2时,记为孤立的点,孤立的点个数加一
            if(sum<0)///只有当前i点操作为1,但有没有孤立的点一直配对,才会出现sum<0的情况
                sum=1;///这时候把这个操作为1的点暂且记作孤立的点,等待下个操作为1的点与之配对。
           /// cout<<"sum="<<sum<<endl;
        }
        if(n%2==1)printf("No\n");
        else
        {///cout<<"*sum="<<sum<<endl;
            if(sum==0)printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a17865569022/article/details/80157500