ArcTan

dfs
随笔 - 16, 文章 - 117, 评论 - 6, 引用 - 0
数据加载中……

POJ 2762-Tarjan + 拓扑排序

题意:给定无向图,判断是否任何两点(x,y),可以从x到y或者从y到x.
         The son can either go from x to y, or from y to x.

思路:Tarjan缩点后,充要条件是,成一条链。拓扑排序求判断之。

#include<stdio.h>
#include
<string.h>
#include
<math.h>
#define maxn 1010
#define maxm 60600


struct edge{
    
int v;
    
int next;
}edges[maxm];
int last[maxn];
int edge_cnt;
void add_edge(int u,int v)
{
    edges[edge_cnt].v 
= v;
    edges[edge_cnt].next 
= last[u];
    last[u] 
= edge_cnt++;
    
return ;
}



int dfn[maxn],low[maxn];
int color[maxn];
bool instack[maxn];
int st[maxn],top;
int cnt,scnt;



int n,m;
int N;
int mat[maxn][maxn];
int topo[maxn];
int dg[maxn];
int path[maxn];


int min(int x,int y)
{
    
return x<y?x:y;
}
void tarjan(int u)
{
    dfn[u]
=low[u]=cnt++;
    st[
++top]=u;
    instack[u]
=1;
    
for (int j=last[u];j!=-1;j=edges[j].next)
    {
        
int v = edges[j].v;
        
if (dfn[v]==-1)
        {
            tarjan(v);
            low[u]
=min(low[u],low[v]);
        }
        
else if (instack[v])
            low[u]
=min(low[u],low[v]);
    }

    
if (low[u]==dfn[u])
    {
        scnt
++;
        
int x;
        
do
        {
            x
=st[top--];
            instack[x]
=0;
            color[x]
=scnt;
        }
while (x!=u);
    }
    
return ;
}
void solve()
{
    cnt 
= 0;
    scnt 
= 0;
    top 
= 0;
    memset(dfn,
-1,sizeof(dfn));  //初始这里居然错了。
    memset(instack,
0,sizeof(instack));
    
for (int i=1;i<=n;i++)
        
if (dfn[i]==-1)
            tarjan(i);
    
return ;
}



void init()
{
    memset(last,
-1,sizeof(last));
    edge_cnt 
= 0;
    scanf(
"%d%d",&n,&m);
    
for (int i=1;i<=m;i++)
    {
        
int u,v;
        scanf(
"%d%d",&u,&v);
        add_edge(u,v);
    }
    
return ;
}
void work()
{
    solve();
    N 
= scnt;//求出的强连通数
    memset(mat,0,sizeof(mat));
    
for (int i=1;i<=n;i++)
    {
        
for (int j=last[i];j!=-1;j=edges[j].next)
        {
            
int v = edges[j].v;
            mat[color[i]][color[v]]
=1;
        }
    }

    return ;
}


bool topsort()
{
    memset(dg,
0,sizeof(dg));
    
for (int i=1;i<=N;i++)
        
for (int j=1;j<=N;j++)
            
if (i!=j)//注意自己到自己不可。当是就在这里WA了!
                dg[i] 
+= mat[j][i];
    
for (int k=1;k<=N;k++)
    {
        
int i=1;
        
while (dg[i]>0 && i<=n) i++;
        
if (i>n)
            
return 0;
        dg[i]
=-1;
        
for (int j=1;j<=N;j++)
            dg[j]
-=mat[i][j];
        path[k]
=i;
    }
    
return 1;
}
int main()
{
    
int cas;
    scanf(
"%d",&cas);
    
while (cas--)
    {
        init();
        work();
        
bool flag = 1;
        topsort();
        
for (int i=1;i<N;i++)
        {
            
if (!mat[path[i]][path[i+1]])
            {
                flag 
= 0;
                
break;
            }
        }
        
if (flag)
            puts(
"Yes");
        
else
            puts(
"No");
    }
    
return 0;
}

/*

3 3
1 2
2 3
3 1

8 11
1 2
2 3
2 5
2 6
3 5
4 3
5 2
5 4
6 7
6 8
7 6

*/


posted on 2012-10-17 17:22 wangs 阅读(255) 评论(0)  编辑 收藏 引用 所属分类: ACM-图论


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理