hdu 3342 Legal or Not(DAG的拓扑排序)

来源:互联网 发布:手机单机小游戏知乎 编辑:程序博客网 时间:2024/06/06 07:43

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3342

题意:给出一个有向图,判断是否有环,也就是问是否是有向无环图(DAG),是则输出YES,否则输出NO,所以可以用是否存在拓扑序列来判断。

解题方案:用入度表的方法,即每次找入度为0的点,然后删掉这个点和由这个点发出的边,循环结束以后判断是不是每个点的入度都为0了,如果是则该DAG存在拓扑序列,否则说明存在环,则不存在拓扑序列

解法一:入度数组+邻接表(vector 动态建表,建表时需要新建对象)

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define FOR(i,k,n) for(int i=k;i<n;i++)#define FORR(i,k,n) for(int i=k;i<=n;i++)#define scan(a) scanf("%d",&a)#define scann(a,b) scanf("%d%d",&a,&b)#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)#define mst(a,n)  memset(a,n,sizeof(a))#define ll long long#define N 105#define mod 1000000007#define INF 0x3f3f3f3fconst double eps=1e-8;const double pi=acos(-1.0);int n,m;int in[N];vector<int> mp[N];queue<int> q;int solve(){    while(!q.empty()) q.pop();    vector<int> v;    FOR(i,0,n) if(in[i]==0) v.push_back(i);    FOR(i,0,v.size())    {        q.push(v[i]);        while(!q.empty())        {            int cur=q.front();            q.pop();            FOR(j,0,mp[cur].size())            {                in[mp[cur][j]]--;                if(in[mp[cur][j]]==0) q.push(mp[cur][j]);            }        }    }    FOR(i,0,n)        if(in[i]) return 0;    return 1;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(~scann(n,m)&&n)    {        FOR(i,0,N) mp[i].clear();        mst(in,0);        FOR(i,0,m)        {            int u,v;            scann(u,v);            mp[u].push_back(v);//建邻接表时需动态新建对象            in[v]++;        }        //FOR(i,0,n) printf("%d ",in[i]);        int ans=solve();        if(ans) printf("YES\n");        else printf("NO\n");    }    return 0;}

解法二:入度数组+邻接表(链式前向星 静态建表,采用静态数组,一次性内存申请),耗时和用vector一样都是31ms,并没有变快啊??是因为vector效率已经很高了?

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define FOR(i,k,n) for(int i=k;i<n;i++)#define FORR(i,k,n) for(int i=k;i<=n;i++)#define scan(a) scanf("%d",&a)#define scann(a,b) scanf("%d%d",&a,&b)#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)#define mst(a,n)  memset(a,n,sizeof(a))#define ll long long#define N 105#define mod 1000000007#define INF 0x3f3f3f3fconst double eps=1e-8;const double pi=acos(-1.0);int n,m;int in[N];queue<int> q;struct Edge{    int to;    //int w;    int next;}E[N];int head[N];//顶点i发出的输入数据中最后一条边的编号int solve(){    while(!q.empty()) q.pop();    vector<int> v;    FOR(i,0,n) if(in[i]==0) v.push_back(i);    FOR(i,0,v.size())    {        q.push(v[i]);        while(!q.empty())        {            int cur=q.front();            q.pop();            for(int j=head[cur];j!=-1;j=E[j].next)            {                int to=E[j].to;                in[to]--;                if(in[to]==0) q.push(to);            }        }    }    FOR(i,0,n)        if(in[i]) return 0;    return 1;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(~scann(n,m)&&n)    {        mst(E,0); mst(head,-1); mst(in,0);        FOR(i,0,m)        {            int u,v;            scann(u,v);            E[i].to=v;            E[i].next=head[u];            head[u]=i;            in[v]++;        }        //FOR(i,0,n) printf("%d ",in[i]);        int ans=solve();        if(ans) printf("YES\n");        else printf("NO\n");    }    return 0;}


0 0
原创粉丝点击