单向连通图 Going from u to v or from v to u? poj2762
http://poj.org/problem?id=2762
强连通求子图和子图关系 + 子图关系是链式结构
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=1e3+10; 15 16 struct node 17 { 18 int d; 19 node *to; 20 }*e[maxn]; 21 22 bool vis[maxn]; 23 24 int num,cnt_st,st[maxn],dfn[maxn],low[maxn],cnt_group,group[maxn],cnt_single,gx[maxn],gy[maxn]; 25 bool vis_st[maxn],ifok; 26 27 void tarjan(int d) 28 { 29 dfn[d]=low[d]=++num; 30 vis[d]=1; 31 st[++cnt_st]=d; 32 node *p=e[d]; 33 while (p) 34 { 35 if (!vis[p->d]) 36 { 37 tarjan(p->d); 38 low[d]=min(low[d],low[p->d]); 39 } 40 else if (!vis_st[p->d]) 41 low[d]=min(low[d],dfn[p->d]); 42 p=p->to; 43 } 44 if (dfn[d]==low[d]) 45 { 46 cnt_group++; 47 while (d!=st[cnt_st]) 48 { 49 group[st[cnt_st]]=cnt_group; 50 vis_st[st[cnt_st]]=1; 51 cnt_st--; 52 } 53 group[st[cnt_st]]=cnt_group; 54 vis_st[st[cnt_st]]=1; 55 cnt_st--; 56 } 57 } 58 59 int main() 60 { 61 node *p; 62 int T,n,m,x,y,i; 63 scanf("%d",&T); 64 while (T--) 65 { 66 scanf("%d%d",&n,&m); 67 for (i=1;i<=n;i++) 68 e[i]=NULL; 69 70 while (m--) 71 { 72 scanf("%d%d",&x,&y); 73 p=new node(); 74 p->d=y; 75 p->to=e[x]; 76 e[x]=p; 77 } 78 79 memset(vis,0,sizeof(vis)); 80 memset(vis_st,0,sizeof(vis_st)); 81 num=0,cnt_st=0,cnt_group=0; 82 for (i=1;i<=n;i++) 83 if (!vis[i]) 84 tarjan(i); 85 86 /* 87 if all are ok:需要的是链式结构 88 1.对于一个子图,最多只有一个子图指向它,最多只有一个子图被它指向(非头结点) 89 2.有且只有一个子图,没有子图指向它(头结点) 90 */ 91 92 ifok=1,cnt_single=0; 93 memset(gx,0,sizeof(gx)); 94 memset(gy,0,sizeof(gy)); 95 for (i=1;i<=n;i++) 96 { 97 p=e[i]; 98 while (p) 99 { 100 ///i -> p->d 101 if (group[p->d]!=group[i]) 102 { 103 if (gx[group[p->d]]==0) 104 gx[group[p->d]]=group[i]; 105 else if (gx[group[p->d]]!=group[i]) 106 ifok=0; 107 108 if (gy[group[i]]==0) 109 gy[group[i]]=group[p->d]; 110 else if (gy[group[i]]!=group[p->d]) 111 ifok=0; 112 } 113 p=p->to; 114 } 115 } 116 for (i=1;i<=cnt_group;i++) 117 if (!gx[i]) 118 cnt_single++; 119 120 printf("%s\n",(ifok&(cnt_single==1))?"Yes":"No"); 121 } 122 return 0; 123 } 124 /* 125 10 126 3 2 127 1 2 128 3 2 129 130 4 3 131 1 2 132 2 3 133 3 1 134 135 3 3 136 1 2 137 2 3 138 3 1 139 140 5 4 141 1 2 142 2 3 143 3 4 144 4 5 145 146 3 2 147 1 2 148 1 3 149 150 3 2 151 1 2 152 3 2 153 154 4 3 155 1 2 156 2 3 157 3 1 158 159 3 3 160 1 2 161 2 3 162 3 1 163 164 5 4 165 1 2 166 2 3 167 3 4 168 4 5 169 170 3 2 171 1 2 172 1 3 173 */
Advance:如何判断两个结点是否属于同一个单向连通子图(就是是否可以从x到y或者从y到x)[多组数据]
强连通图,同一个集合内的点,可以互相到达
拓扑结构,point a in group x, point b in group y,如x能到达y,则a能到b,但b不能到a。
其它情况下,两者均不能到达对方。
在拓扑结构中,一个点也许有多个孩子,多个祖先。
没有想到什么好的方法。。。不过感觉应该有。
TLE代码
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 //#include <map> 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=1e3+10; 16 17 struct node 18 { 19 int d; 20 node *to; 21 }*e[maxn]; 22 23 bool vis[maxn],f[maxn][maxn]; 24 int c,q[maxn]; 25 26 //void dfs(int d) 27 //{ 28 // vis[d]=1; 29 // f[c][d]=1; 30 // node *p=e[d]; 31 // while (p) 32 // { 33 // if (!vis[p->d]) 34 // dfs(p->d); 35 // p=p->to; 36 // } 37 //} 38 39 //map<int,int> ma; 40 41 int main() 42 { 43 node *p; 44 int T,n,m,x,y,i,j; 45 int head,tail,d; 46 int num; 47 bool v; 48 scanf("%d",&T); 49 while (T--) 50 { 51 scanf("%d%d",&n,&m); 52 for (i=1;i<=n;i++) 53 e[i]=0; 54 // ma.clear(); 55 num=0; 56 while (m--) 57 { 58 scanf("%d%d",&x,&y); 59 // if (ma.find(x)!=ma.end()) 60 // x=ma[x]; 61 // else 62 // ma[x]=++num,x=num; 63 // if (ma.find(y)!=ma.end()) 64 // y=ma[y]; 65 // else 66 // ma[y]=++num,y=num; 67 68 69 p=new node(); 70 p->d=y; 71 p->to=e[x]; 72 e[x]=p; 73 } 74 for (c=1;c<=n;c++) 75 { 76 // memset(vis,0,sizeof(vis)); 77 // dfs(c); 78 79 q[1]=c; 80 vis[c]=1; 81 head=0,tail=1; 82 while (head<tail) 83 { 84 head++; 85 d=q[head]; 86 p=e[d]; 87 while (p) 88 { 89 if (!vis[p->d]) 90 { 91 vis[p->d]=1; 92 q[++tail]=p->d; 93 f[c][p->d]=1; 94 } 95 p=p->to; 96 } 97 } 98 for (j=1;j<=tail;j++) 99 vis[q[j]]=0; 100 } 101 102 v=1; 103 for (i=1;i<=n;i++) 104 for (j=i+1;j<=n;j++) 105 if (!f[i][j] && !f[j][i]) 106 v=0; 107 printf("%s\n",v?"Yes":"No"); 108 } 109 return 0; 110 }