Description
Input
Output
Sample Input
1 3 3 1 2 2 3 3 1
Sample Output
Yes
题意:给出的图是否可以随意的指定某两点:从u可以到v 或者从v到u。这里注意的是题目给出的是or!!!!不是双向连通的,而单连通!
思路:那么根据题目意思,就可以用Tarjan算法缩点后,重新建图,然后对新图进行拓扑排序,然后拓扑排序后的点与新图所有的结点总数相同,就说明是单连通的,反之……
不过有剪枝:就是如果出度为0的点有多个,那么肯定不能从u到v,或者从v到u,因为出度为0,所以就没有边连接u和v了;如果新建的图只有一个结点,那么直接是对的。
这题也是WA了好多发,昨天下午做到CF开始都没对,代码都已经早就写好了,改了5个小时都没对,后面晚上回来改也不对,今天做了H题,然后也是一直错,后面单步调试才发现在Tarjan中把min写成了max,靠!!!!!!!!!!!!!!!!!!!!!!细节决定成败啊!!!!!!!!!!做了整整两天了!!!!!
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <list> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define pri(a) printf("%d\n",a) #define MM 10002 #define MN 1005 #define INF 168430090 using namespace std; typedef long long ll; int n,m,cnt,tem,Count,DFN[MN],LOW[MN],id[MN],vis[MN],suo[MN],q2[MN],Map[MN][MN]; stack<int>p; vector<int>q[MN],q1[MN]; void tarjan(int u) { int j,v; DFN[u]=LOW[u]=++cnt; vis[u]=1; q2[++tem]=u; for(j=0;j<q[u].size();j++) { v=q[u][j]; if(!DFN[v]) { tarjan(v); LOW[u]=min(LOW[u],LOW[v]); //和H题一样也是把min写成max,所以一直错都不知道,H题的Tarjan算法是从这里拿过去的,所以那题改过来了才知道这题也是这里错,改过来再提交直接AC,唉……昨晚搞到1点都不知道是这里错,大意了! } else if(vis[v]&&DFN[v]<LOW[u]) LOW[u]=DFN[v]; } if(DFN[u]==LOW[u]) { Count++; do { v=q2[tem--]; vis[v]=0; suo[v]=Count; }while(v!=u); } } void solve() { Count=cnt=tem=0; mem(DFN,0); for(int i=1;i<=n;i++) if(!DFN[i]) tarjan(i); } int topsort() { if(Count==1||n==1) return 1; //如果新建的图只有一个结点,或者原图只有一条边,那肯定对啦 int i,v,u,sum=0; for(i=1;i<=Count;i++) if(!id[i]) p.push(i); while(!p.empty()) { if(p.size()>1) return 0; //出度超过2个结点肯定不对 u=p.top(); p.pop(); sum++; for(v=0;v<q1[u].size();v++) if(--id[q1[u][v]]==0) p.push(q1[u][v]); } if(sum!=Count) return 0; return 1; } void suodian() { for(int i=1;i<=n;i++) for(int j=0;j<q[i].size();j++) if(suo[q[i][j]]!=suo[i]&&!Map[suo[q[i][j]]][suo[i]]) { id[suo[q[i][j]]]++; q1[suo[i]].push_back(suo[q[i][j]]); Map[suo[q[i][j]]][suo[i]]=1; } } void init() { for(int i=0;i<=n;i++) { q[i].clear(); q1[i].clear(); } while(!p.empty()) p.pop(); mem(vis,0); mem(suo,0); mem(id,0); mem(Map,0); } int main() { int t,u,v; sca(t); while(t--) { init(); //多case需要初始化 scanf("%d%d",&n,&m); while(m--) { scanf("%d%d",&u,&v); q[u].push_back(v); } solve(); suodian(); if(topsort()) puts("Yes"); else puts("No"); } return 0; }