二分查找第一次出现的位置
nlogn的最长不下降子序列

poj 2762 半连通图判断

scturtle posted @ 2011年3月22日 19:59 in algorithm , 3730 阅读

昨天算法课讲了强连通kosaraju算法,今天做课后题看到半连通问题,好久没做题了,就想写一写,证明自己的一些想法,结果悲剧了,各种无语的小错误......

题意其实就是判断图是否是半连通的,强连通缩点后:

1.拓扑排序判断每次队列中是否只有一个元素,看来的

#include <cstdio>
#include <cstring>
#include <vector>
#include <deque>
#include <cstdlib>
using namespace std;

int T,n,m;
bool vit[1001];
int ind[1001];
int mark[1001],scc;
deque<int> f;
vector<int> g[1001];
vector<int> gt[1001];
bool chong[1001][1001];
vector<int> *gs=gt;
void dfs(int s);
void dfsmain()
{
    memset(vit,false,sizeof(vit));
    f.clear();
    for(int i=1;i<=n;i++)
        if(!vit[i]) dfs(i);
}
void dfs(int s)
{
    vit[s]=1;
    for(unsigned i=0;i<g[s].size();i++)
        if(!vit[g[s][i]]) dfs(g[s][i]);
    f.push_front(s);
}
void tdfs(int s);
void tdfsmain()
{
    memset(mark,0,sizeof(mark));scc=0;
    memset(vit,0,sizeof(vit));
    while(!f.empty())
    {
        int u=f.front();f.pop_front();
        if(!vit[u])
            ++scc,tdfs(u);
    }
}
void tdfs(int s)
{
    vit[s]=1;mark[s]=scc;
    for(unsigned i=0;i<gt[s].size();i++)
        if(!vit[gt[s][i]]) tdfs(gt[s][i]);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    int u,v;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            g[i].clear(),gt[i].clear();
        while(m--)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            gt[v].push_back(u);
        }
        dfsmain();
        tdfsmain();
        //for(int i=1;i<=n;i++)
            //printf("%d ",mark[i]);
        //puts("");

        memset(ind,0,sizeof(ind));
        memset(chong,0,sizeof(chong));
        for(int i=1;i<=scc;i++)
            gs[i].clear();
        for(u=1;u<=n;u++)
            for(unsigned i=0;i<g[u].size();i++)
            {
                v=g[u][i];
                if(mark[u]!=mark[v] && !chong[mark[u]][mark[v]])
                    gs[mark[u]].push_back(mark[v]),
                        ind[mark[v]]++, chong[mark[u]][mark[v]]=1;
            }
        deque<int> q;
        for(int i=1;i<=scc;i++)
            if(!ind[i])
                q.push_back(i);
        bool failed=0;
        while(!q.empty())
        {
            if(q.size()!=1)
            {failed=1; break;}
            int u=q.front();q.pop_front();
            for(unsigned i=0;i<gs[u].size();i++)
            {
                int v=gs[u][i];
                if(--ind[v]==0)
                    q.push_back(v);
            }
        }
        if(failed)
            puts("No");
        else
            puts("Yes");
    }
}

2.或者直接dfs狂搜(不管是否已vit),得到dfs的最大深度,是否等于点数,看所有点是否能在一条路上,代码好写.

#include <cstdio>
#include <cstring>
#include <vector>
#include <deque>
#include <cstdlib>
using namespace std;

int T,n,m;
bool vit[1001];
int ind[1001];
int mark[1001],scc;
deque<int> f;
vector<int> g[1001];
vector<int> gt[1001];
bool chong[1001][1001];
vector<int> *gs=gt;
void dfs(int s);
void dfsmain()
{
    memset(vit,false,sizeof(vit));
    f.clear();
    for(int i=1;i<=n;i++)
        if(!vit[i]) dfs(i);
}
void dfs(int s)
{
    vit[s]=1;
    for(unsigned i=0;i<g[s].size();i++)
        if(!vit[g[s][i]]) dfs(g[s][i]);
    f.push_front(s);
}
void tdfs(int s);
void tdfsmain()
{
    memset(mark,0,sizeof(mark));scc=0;
    memset(vit,0,sizeof(vit));
    while(!f.empty())
    {
        int u=f.front();f.pop_front();
        if(!vit[u])
            ++scc,tdfs(u);
    }
}
void tdfs(int s)
{
    vit[s]=1;mark[s]=scc;
    for(unsigned i=0;i<gt[s].size();i++)
        if(!vit[gt[s][i]]) tdfs(gt[s][i]);
}
int maxl;
void finaldfs(int s,int l)
{
    if(l>maxl) maxl=l;
    for(unsigned i=0;i<gs[s].size();i++)
        finaldfs(gs[s][i],l+1);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    int u,v;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            g[i].clear(),gt[i].clear();
        while(m--)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            gt[v].push_back(u);
        }
        dfsmain();
        tdfsmain();
        //for(int i=1;i<=n;i++)
            //printf("%d ",mark[i]);
        //puts("");

        memset(ind,0,sizeof(ind));
        memset(chong,0,sizeof(chong));
        for(int i=1;i<=scc;i++)
            gs[i].clear();
        for(u=1;u<=n;u++)
            for(unsigned i=0;i<g[u].size();i++)
            {
                v=g[u][i];
                if(mark[u]!=mark[v] && !chong[mark[u]][mark[v]])
                    gs[mark[u]].push_back(mark[v]),
                        ind[mark[v]]++, chong[mark[u]][mark[v]]=1;
            }
        maxl=0;
        for(int i=1;i<=scc;i++)
            if(!ind[i])
                finaldfs(i,1);
        if(maxl==scc)
            puts("Yes");
        else
            puts("No");
    }
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter