题目描述
传销组织 传销组织 GPLT的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的
宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟的 宗旨是“有志者事竟成”,他们最近在执行一项宏伟N人计划,以 人计划,以 人计划,以 人计划,以 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说, 构建科学有效的情报网。换句话说,
构建科学有效的情报网。换句话说, GPLT组织希望建一个由 组织希望建一个由 组织希望建一个由 组织希望建一个由 组织希望建一个由 N个人和若干单向私有电话 个人和若干单向私有电话 个人和若干单向私有电话 个人和若干单向私有电话 个人和若干单向私有电话 个人和若干单向私有电话 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类:
线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类: 线构成的情报网,并使得满足一系列要求。这些分两类:
① 从第 a个人通过 个人通过 1条或多电话线 条或多电话线 条或多电话线 条或多电话线 可以 联系到第 联系到第 b个人。
② 从第 a个人通过 个人通过 1条或多电话线 条或多电话线 条或多电话线 条或多电话线 不能 联系到第 联系到第 b个人。
现在 GPLT组织的首脑 组织的首脑 组织的首脑 gluo请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这
请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 请你帮忙给出一个满足所有要求的情报网,或者告诉他这 样的情报网是不可能存在。 样的情报网是不可能存在。 样的情报网是不可能存在。 样的情报网是不可能存在。 样的情报网是不可能存在。 样的情报网是不可能存在。
输入格式
每个测试点包含若干组数据, 每个测试点包含若干组数据, 每个测试点包含若干组数据, 每个测试点包含若干组数据, 每个测试点包含若干组数据, 每个测试点包含若干组数据, 以 EOF结尾, 对于每组数据: 对于每组数据: 对于每组数据: 对于每组数据:
第一行 第一行 1个整数 N,表示情报网的人数。 ,表示情报网的人数。 ,表示情报网的人数。 ,表示情报网的人数。 ,表示情报网的人数。
第二行 第二行 1个整数 M,表示 ,表示 ①类要求的个数,接下来 ①类要求的个数,接下来 ①类要求的个数,接下来 ①类要求的个数,接下来 ①类要求的个数,接下来 ①类要求的个数,接下来 M行 每行 每2个整数 个整数 a, b。
第 M+3行 1个整数 个整数 T,表示②类要求的个数, , 表示②类要求的个数, 表示②类要求的个数, 表示②类要求的个数, 表示②类要求的个数, 表示②类要求的个数接下来 接下来 T行 每行 每2个整数 a, b。
输出格式
对于测试点中的每组数据, 对于测试点中的每组数据, 对于测试点中的每组数据, 对于测试点中的每组数据, 对于测试点中的每组数据, 对于测试点中的每组数据, 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 若不存在这样的情报网,输出 NO。否则在第一行输出 否则在第一行输出 否则在第一行输出 否则在第一行输出 YES, 在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量
在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量 在第二行输出情报网中电话线的数量 P,接下来 ,接下来 ,接下来 ,接下来 P行 每行 每2个整数描述电话线 个整数描述电话线 个整数描述电话线 个整数描述电话线 个整数描述电话线 。由于资源有 由于资源有 由于资源有 限,要求 限,要求 P<=N+M+T。
样例输入
3
2
1 2
2 3
1
3 1
3
2
1 2
2 3
1
1 3
样例输出
YES
2
1 2
2 3
NO
样例 输入 输出 2
见试题文件夹下的 见试题文件夹下的 见试题文件夹下的 见试题文件夹下的 gplt.in/ans。
数据范围与约定
对于 20%的数据 的数据 ,1 ≤ N ≤ 100。
对于 60%的数据 的数据 ,1 ≤ N ≤ 25000。
对于 100%的数据 的数据 ,1 ≤ N, M, T ≤ 100000,1 ≤ a, b ≤ N,a≠b,要求输出的 要求输出的 要求输出的 P<=N+M+T。
首先这题第一步肯定是给m的要求直接连上有向边,感性上来说。它对第二种操作的影响会比较小。然后就是快速求有向图的连通性。然而似乎并没有什么低于n^2的做法。。。(事后好像标算不过是压了个位)。然后为了避免爆内存分了个块。。。也是有点玄学。
然而我显然不认为n^2是可以过得。。。于是我就写了个非常玄学的记忆化时间空间复杂度都非常深不可测。。。。第4个点跑了1.5秒。第五个点跑了5秒,第6个点144秒。。。然而这三个点大小其实差不多。。。其他点(包括数据更大的)都在1秒以内了。。。看上去似乎超出了我乱搞的预期。
但是我一开始却爆0了。。。因为多组数据是个坑啊。。。一般人做到no的时候就直接break了。。。然后继续读数据就会混乱掉。。。日狗。。。
#include <cstdio> #include <cmath> #include <ctime> #include <string> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <set> #include <stack> #include <queue> #include <vector> #include<map> #include<list> #define pb push_back #define lb lower_bound #define sqr(x) (x)*(x) #define lowbit(x) (x)&(-x) #define Abs(x) ((x) > 0 ? (x) : (-(x))) #define forup(i,a,b) for(int i=(a);i<=(b);i++) #define fordown(i,a,b) for(int i=(a);i>=(b);i--) #define ls(a,b) (((a)+(b)) << 1) #define rs(a,b) (((a)+(b)) >> 1) #define getlc(a) ch[(a)][0] #define getrc(a) ch[(a)][1] #define maxn 100005 #define maxm 100005 #define INF 1070000000 using namespace std; typedef long long ll; typedef unsigned long long ull; template<class T> inline void read(T& num){ num = 0; bool f = true;char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();} while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();} num = f ? num: -num; } int out[100]; template<class T> inline void write(T x,char ch){ if (x==0) {putchar('0'); putchar(ch); return;} if (x<0) {putchar('-'); x=-x;} int num=0; while (x){ out[num++]=(x%10); x=x/10;} fordown(i,num-1,0) putchar(out[i]+'0'); putchar(ch); } /*==================split line==================*/ int n,m,t; map<int,bool> f[maxn]; vector<int> g1[maxn],g2[maxn]; vector<int> s; vector<int> G[maxn]; int cnt=0; bool vis[maxn]; int id[maxn]; void dfs1(int x) { vis[x]=1; for(int i=0;i<g1[x].size();i++) { int v=g1[x][i]; if(!vis[v]) { dfs1(v);} } s.pb(x); } void dfs2(int x) { id[x]=cnt; for(int i=0;i<g2[x].size();i++) { int v=g2[x][i]; if(!id[v]) dfs2(v); } } bool work(int x,int y) { if(f[x].count(y)!=0) { return f[x][y];} for(int i=0;i<G[x].size();i++) { int v=G[x][i]; f[x][y]=work(v,y); if(f[x][y]==true) return true; } return false; } void clearall() { forup(i,1,n) {f[i].clear(); g1[i].clear();g2[i].clear();} forup(i,1,cnt) G[i].clear(); s.clear(); } int main() { freopen("gplt.in","r",stdin); freopen("gplt.out","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; clearall(); forup(i,1,m) { int x,y; read(x);read(y); g1[x].pb(y);g2[y].pb(x); } memset(vis,0,sizeof(vis)); forup(i,1,n) { if(!vis[i]) dfs1(i); } for(int i=s.size()-1;i>=0;i--) { int v=s[i]; if(!id[v]) {cnt++; dfs2(v);} } forup(i,1,n) for(int j=0;j<g1[i].size();j++) { int v=g1[i][j]; f[id[i]][id[v]]=1; } forup(i,1,cnt) for(map<int,bool>::iterator j=f[i].begin();j!=f[i].end();j++) {int v=j->first;G[i].pb(v);} read(t); bool flag=1; forup(i,1,t) { int x,y;read(x);read(y); if(flag==0) continue; if(id[x]==id[y]) { flag=0;printf("NO\n"); continue; } bool ans=work(id[x],id[y]); if(ans) {flag=0;printf("NO\n");continue;} } if(flag==1) {printf("YES\n"); write(m,'\n'); forup(x,1,n) for(int y=0;y<g1[x].size();y++) { int v=g1[x][y]; write(x,' ');write(v,'\n'); } } } return 0; }