4594: [Shoi2015]零件组装机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 69 Solved: 26
[ Submit][ Status][ Discuss]
Description
曾经发明了激光发生器的发明家SHTSC又公开了他的新发明:零件组装机--一种可以生产并组装零件的神秘装置。
一个零件是一张顶点由0 到n-1标号的无向图,零件组装机由以下两条功能。
(1)生产一个仅有一个顶点标号为0而没有边的零件。
(2)组合两个已有的零件G1,G2,且G2的顶点数m>=G1的顶点数n,得到新的零件G。G的顶点集合是G1、G2顶点集合的并
集,并且G2的顶点i(0<=i<m)被重新标号为n+i。G的边集是G1、G2边集的并集再对所有标号为a(a>=n)的顶点添加一
条连接(a,a mod n)的无向边。

现在SHTSC正在思考,对于一个给定的零件,能否由零件组装机生产组装得到。注意:零件是带标号的,这意味着
两个零件即使仅有标号不同也被视为不同的零件。为了帮助你理解问题,SHTSC特地给了你顶点数<=5的零件的图例。

Input
第一行一个整数t,表示有t组数据。
每组数据的第一行两个整数n,m。表示某个带标号的无向图有n个顶点0到n-1标号,m是边的数量。
接下来m行,每行两个整数u,v表示一条从u到v的无向边。
t<=10,n,m<=100000,0<=u, v<n
Output
对于每组数据,输出一行。如果这个无向图可以被零件制造机制造输出"YES"否则输出"NO"。
Sample Input
2
1 0
2 0
1 0
2 0
Sample Output
YES
NO
//样例1:n=1的情况和一个不能被产生的零件
NO
//样例1:n=1的情况和一个不能被产生的零件
HINT
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E5 + 10;
struct E{
int x,y;
E(){}
E(int x,int y): x(x),y(y){}
bool operator < (const E &b) const {return x < b.x;}
}e[maxn];
int t,L[maxn];
bool bo[maxn];
bool Judge(int n,int l,int r)
{
if (n == 1) return l == r;
if (l == r) return 0;
for (int i = 0; i < n; i++)
L[i] = maxn,bo[i] = 0;
for (int i = l; i < r; i++) {
int x = e[i].x;
int y = e[i].y;
if (x == L[y]) return 0;
L[y] = min(L[y],x);
}
for (int i = 0; i < n; i++)
if (L[i] == 0) bo[i] = 1;
else if (L[i] - L[i-1] == 1 && bo[i-1]) bo[i] = 1;
int flag = 0,siz;
for (int i = 0; i < n/2; i++) {
siz = i + 1;
bool ok = 1;
for (int j = i + siz; j < n; j += siz) {
if (bo[j] && L[j] == i) continue;
ok = 0; break;
}
if (ok) {flag = 1; break;}
}
if (!flag) return 0;
int p1 = l,p2;
for (int i = l; i < r; i++) {
int x = e[i].x;
int y = e[i].y;
if (x == siz) break;
if (y < siz) e[p1++] = e[i];
}
p2 = p1;
for (int i = l; i < r; i++) {
int x = e[i].x;
int y = e[i].y;
if (x < siz) continue;
e[p2++] = E(e[i].x - siz,e[i].y - siz);
}
return Judge(siz,l,p1) && Judge(n - siz,p1,p2);
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
t = getint();
while (t--) {
int n,m;
n = getint();
m = getint();
for (int i = 0; i < m; i++) {
int x = getint();
int y = getint();
e[i] = E(min(x,y),max(x,y));
}
sort(e,e + m);
if (Judge(n,0,m)) puts("YES");
else puts("NO");
}
return 0;
}