Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 17993 | Accepted: 4816 |
Description
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
Input
The first line contains a single integer T, the number of test cases. And followed T cases.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
Output
The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.
Sample Input
1 3 3 1 2 2 3 3 1
Sample Output
Yes
题目大意就是给你张图,问你是否任意两点u,v 可以从u到v或者从v到u
两种解法 先贴拓扑的
另外有些数据
1
3 2
1 2
3 2
1
3 3
1 2
1 3
2 3
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=1008; const int M=6008; int head[N],dfn[N],in[N],low[N],bl[N],q[N]; int tot,cnt,scnt,n,m,l; bool instack[N]; bool adj[N][N]; struct node{ int u,to,next; }e[M<<1]; void init(){ memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); memset(in,0,sizeof(in)); memset(head,-1,sizeof(head)); memset(adj,0,sizeof(adj)); l=tot=cnt=scnt=0; } void add(int u,int v){ e[tot].u=u;e[tot].to=v;e[tot].next=head[u];head[u]=tot++; } void Tajan(int u){ instack[u]=1; q[l++]=u; low[u]=dfn[u]=++cnt; for(int i=head[u];i+1;i=e[i].next){ int v=e[i].to; if(!dfn[v]) { Tajan(v); low[u]=min(low[u],low[v]); } else if(instack[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]){ int t; ++scnt; do{ t=q[--l]; instack[t]=0; bl[t]=scnt; }while(t!=u); } } bool Ju(int u){ while(scnt--){ int cont=0; for(int i=head[u];i+1;i=e[i].next){ int v=e[i].to; --in[v]; if(in[v]==0) { cont++;u=v; } } if(cont>1) return 0; } return 1; } int main(){ int T,u,v; for(scanf("%d",&T);T--;){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;++i){ scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;++i) if(!dfn[i]) Tajan(i); memset(head,-1,sizeof(head)); for(int i=0;i<tot;++i){ u=e[i].u,v=e[i].to; if(bl[u]==bl[v]||adj[u][v]) continue; else { adj[bl[u]][bl[v]]=1; // 注意这里 add(bl[u],bl[v]); ++in[bl[v]]; } } int cont=0,k; for(int i=1;i<=scnt;++i) if(!in[i]) {++cont;k=i;} if(cont>1) {puts("No");continue;} else { if(Ju(k)) puts("Yes"); else puts("No"); } } }
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int MAXN = 20010; const int MAXM = 100010; struct Edge{ int to, next; }edge[MAXM]; int head[MAXN], tot; int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN]; int Index, top; int scc; bool Instack[MAXN]; int num[MAXN]; int n, m; void init() { tot = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for (int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (!DFN[v]) { Tarjan(v); if (Low[u] > Low[v]) Low[u] = Low[v]; } else if (Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if (Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; Instack[v] = false; Belong[v] = scc; num[scc]++; } while (v != u); } } void solve() { memset(Low, 0, sizeof(Low)); memset(DFN, 0, sizeof(DFN)); memset(num, 0, sizeof(num)); memset(Stack, 0, sizeof(Stack)); memset(Instack, false, sizeof(Instack)); Index = scc = top = 0; for (int i = 1; i <= n; i++) if (!DFN[i]) Tarjan(i); } vector<int> g[MAXN]; int linker[MAXN], used[MAXN]; bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (!used[v]) { used[v] = 1; if (linker[v] == -1 || dfs(linker[v])) { linker[v] = u; return true; } } } return false; } int hungary() { int res = 0; memset(linker, -1, sizeof(linker)); for (int i = 1; i <= scc; i++) { memset(used, 0, sizeof(used)); if (dfs(i)) res++; } return (scc - res)==1; } int main() { int cas; scanf("%d", &cas); while (cas--) { scanf("%d%d", &n, &m); init(); int u, v; for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); addedge(u, v); } solve(); for (int i = 0; i <= scc; i++) g[i].clear(); for (int u = 1; u <= n; u++) { for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (Belong[u] != Belong[v]) g[Belong[u]].push_back(Belong[v]); } } if(hungary()) puts("Yes"); else puts("No"); } return 0; }