您的位置:首页 > 编程语言 > Go语言

poj 2762 Going from u to v or v to u (tarjan+缩点+dfs搜索)

2013-08-04 00:25 405 查看
这道题大致想法没有问题,首先要缩点,然后重构图,判断重构的图是不是弱连通。这里有分析可知,不管图是什么样的,里面一定存在一条链,从入度为0的点走到出度为0的点,这一路上要包括所有的点。要想任意两点都能弱连通,那么必然边的方向是一定。

tarjan缩点,重构图就不用解释了,主要是后面怎么判断DAG是不是有一条链包括所有的点。这里用的是dfs搜索,查过其他牛们的博客,还有拓扑排序(如果删掉一个点后,新出现两个或多个入度为的点,说明这些新出现的入度0的点都是来自删去的点,它们之间不连通),还有就是dp方法求DAG最长路径,看最长路径上的点数是不是等于DAG上总点数,是的话就存在这条链,否则不可以。

代码:

#include <cstdio>
#include <vector>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;

const int N = 1010;
int pre
, lowlink
, sccno
, scc_cnt, dfs_clock;
int in
, out
, g

;
int T, n, m;
vector<int> G
;
stack<int> S;

void dfs( int u )
{
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for ( int i = 0; i < G[u].size(); ++i ) {
int v = G[u][i];
if ( !pre[v] ) {
dfs(v);
lowlink[u] = min( lowlink[u], lowlink[v] );
}
else if ( !sccno[v] ) lowlink[u] = min ( pre[v], lowlink[u] );
}
if ( lowlink[u] == pre[u] ) {
scc_cnt++;
for (;;) {
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
if ( x == u ) break;
}
}
}
void tarjan()
{
dfs_clock = scc_cnt = 0;
memset(pre, 0, sizeof(pre));
memset(sccno, 0, sizeof(sccno));
for ( int i = 1; i <= n; ++i ) if ( !pre[i] ) dfs(i);
}
bool vis
;
bool jv()
{
for ( int i = 1; i <= scc_cnt; ++i ) if ( !vis[i] ) {
printf("v %d\n", i);
return false;
}
return true;
}
bool judge( int x, int pn )
{
//printf("pn %d\n", pn);
if ( pn == scc_cnt && jv() ) {
//printf("x %d\n", x);
return true;
}
for ( int i = 1; i <= scc_cnt; ++i ) {
if ( g[x][i] && !vis[i] ) {
vis[i] = 1;
if ( judge( i, pn+1 ) ) return true;
vis[i] = 0;
}
}
return false;
}
int main()
{
scanf("%d", &T);
while ( T-- ){
scanf("%d%d", &n, &m);
for ( int i = 0; i <= n; ++i ) G[i].clear();
while ( m-- ) {
int a, b;
scanf("%d%d", &a, &b);
G[a].push_back(b);
}
tarjan();
if ( scc_cnt == 1 ) { printf("Yes\n"); continue; }

memset( out, 0, sizeof(out));
memset( in, 0, sizeof(in));
memset( g, 0, sizeof(g));
memset( vis, 0, sizeof(vis));
int r0c1 = 0, r1c1 = 0, r1c0 = 0;
for ( int i = 1; i <= n; ++i ) {
for ( int j = 0; j < G[i].size(); ++j ) {
int v = G[i][j];
if ( sccno[i] != sccno[v] ) {
g[sccno[i]][sccno[v]] = 1;
in[sccno[v]]++;
}
}
}
int s, ans = 0;
for ( int i = 1; i <= scc_cnt&&ans<=1; ++i ) if ( !in[i] ) s = i, ans++;
vis[s] = 1;
//printf("%d\n", s);
//for ( int i = 1; i <= scc_cnt; ++i ) for ( int j = 1; j <= scc_cnt; ++j ) if ( g[i][j] ) printf("g %d %d\n", i, j);
if ( ans > 1 ) printf("No\n");
else if ( judge(s, 1) ) printf("Yes\n");
else printf("No\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: