题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6029
题意:有一种图叫“Cool Graph”,从2号顶点到n号顶点每个顶点都有2种选择:(1)和前面所有的顶点(1 ~ i-1)都相连 (2)和前面所有的顶点都不相连。给出这些顶点的选择,问这个“Cool Graph”是否存在完美匹配(边的集合,使得图的每个顶点覆盖且仅覆盖一次)。
解题方案:
可以发现
- 当n为奇数时,一定不存在完美匹配,因为每条被选中的边都一定是覆盖2个点,所以最后只能覆盖到偶数个点。
- 当n为偶数时
- 当最后一个顶点的选择是2时,一定不存在完美匹配,因为这时候最后一个顶点就是孤立点了,故不存在完美匹配
- 当最后一个顶点的选择是1时,这是讨论的重点,下面进行进一步的讨论
对最后一种情况,因为在选择序列中,2只能由后面的1连,所以猜测:从后往前遍历,遇到每个2的时候check一下当前2的个数是不是小于或等于1的个数,若此条件一直成立,则此“Cool Graph”存在完美匹配。
证明:
- 必要性(上述条件是存在完美匹配的必要条件)
- 用反证法来证明:当“Cool Graph”存在完美匹配时(大前提),假设上述条件不满足,则在某个2的位置它不能被后面的1连上(因为后面的1已经全被连完了),此时不存在完美匹配,与大前提矛盾,故假设不成立,即必要性成立。
- 充分性(上述条件是存在完美匹配的充分条件)
- 直接证明:当上述条件成立时,选择序列中每个2都能被后面的1连上,然后一定剩下偶数个1,这偶数个1形成了一个完全图,随便怎么连都行,所以足够使完美匹配存在。
所以上述条件是“Cool Graph”存在完美匹配的充要条件,所以只需对上述条件进行判断就可以了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define FOR(i,k,n) for(int i=k;i<n;i++)
#define FORR(i,k,n) for(int i=k;i<=n;i++)
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,n) memset(a,n,sizeof(a))
#define ll long long
#define N 100005
#define mod 1000000007
#define INF 0x3f3f3f3f
const double eps=1e-8;
const double pi=acos(-1.0);
int a[N];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
FORR(i,1,n-1) cin>>a[i];
if(n&1) printf("No\n");
else
{
if(a[n-1]==2) printf("No\n");
else
{
int flag=1;
int cnt1=0,cnt2=0;
for(int i=n-1;i>=1;i--)
{
if(a[i]==1) cnt1++;
else
{
cnt2++;
if(cnt2>cnt1)
{
flag=0;
break;
}
}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
}
}
return 0;
}