【1】Reward HDU - 2647
拓扑排序,反向建边
AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int reward[N];
vector<int>pic[N];
int n,m;
struct node
{
    int num,degree;
}work[N];
queue<node>que;
int solve()
{
    int ans=0,cnt=0;
    while(!que.empty())
        que.pop();
    for(int i=1;i<=n;i++)
    {
        if(work[i].degree==0)
        {
            que.push(work[i]);
            reward[i]=888;
            ans+=888;
        }
    }
    while(!que.empty())
    {
        node now=que.front();
        que.pop();
        cnt++;
        for(int i=0;i<pic[now.num].size();i++)
        {
            int tmp=pic[now.num][i];
            work[tmp].degree--;
            if(work[tmp].degree==0)
            {
                reward[tmp]=reward[now.num]+1;
                ans+=reward[tmp];//每次发现有点的度为0,就计算
                que.push(work[tmp]);
            }

        }
    }
    return cnt==n?ans:-1;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(work,0,sizeof(work));
        for(int i=1;i<=n;i++)
        {
            reward[i]=0;
            pic[i].clear();
            work[i].num=i;
        }
        int a,b;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            pic[b].push_back(a);
            work[a].degree++;
        }
        printf("%d\n",solve());
    }
    return 0;
}

错误代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int pre[N],reward[N];//不能用pre数组,因为一个点的父亲可能有多个,但入度先为0的不一定是pre数组里面存的点
vector<int>pic[N];
int ans,n,m,cnt;
struct node
{
    int num,degree;
}work[N];
queue<node>que;
void solve()
{
    while(!que.empty())
        que.pop();
    for(int i=1;i<=n;i++)
    {
        if(work[i].degree==0)
            que.push(work[i]);
    }
    while(!que.empty())
    {
        node now=que.front();
        que.pop();
        if(pre[now.num]==now.num)
        {
            reward[now.num]=888;
            ans+=reward[now.num];
            cnt++;
        }
        else
        {
            reward[now.num]=reward[pre[now.num]]+1;
            ans+=reward[now.num];
            cnt++;
        }
        for(int i=0;i<pic[now.num].size();i++)
        {
            int tmp=pic[now.num][i];
            work[tmp].degree--;
            if(work[tmp].degree==0)
                que.push(work[tmp]);
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(work,0,sizeof(work));
        for(int i=1;i<=n;i++)
        {
            pre[i]=i;
            reward[i]=0;
            pic[i].clear();
            work[i].num=i;
        }
        int a,b;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            pic[b].push_back(a);
            pre[a]=b;
            work[a].degree++;
        }
        ans=0;
        cnt=0;
        solve();
        if(cnt<n)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

【2】Legal or Not HDU - 3342
拓扑排序判环:

#include <bits/stdc++.h>
using namespace std;
const int N=105;
vector<int>pic[N];
int degree[N];
queue<int>que;
bool solve(int n)
{
    int cnt=0;
    while(!que.empty())
        que.pop();
    for(int i=0;i<n;i++)
    {
        if(degree[i]==0)
        {
            que.push(i);
            cnt++;
        }
    }
    while(!que.empty())
    {
        int now=que.front();
        que.pop();
        for(int i=0;i<pic[now].size();i++)
        {
            int tmp=pic[now][i];
            degree[tmp]--;
            if(degree[tmp]==0)
            {
                cnt++;
                que.push(tmp);
            }
        }
    }
    return cnt==n?1:0;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m),n)
    {
        int x,y;
        for(int i=0;i<n;i++)
        {
            pic[i].clear();
            degree[i]=0;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            pic[x].push_back(y);
            degree[y]++;
        }
        if(solve(n))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

【3】Triangle LOVE HDU - 4324
拓扑排序判断是否有三元环
题意:给出一任意两点间有且仅有一条单向边的有向图,要求判断这个图中是否存在仅有3个结点构成的环。
我的解法是先计算能进行拓扑排序的节点cnt,如果cnt+3<=n,再用dfs判断是否存在三元环。
AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N=2010;
vector<int>pic[N];
char ss[N];
bool vis[N];
int degree[N];
queue<int>que;
bool flag;
bool solve(int n)
{
    int cnt=0;
    while(!que.empty())
        que.pop();
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            vis[i]=1;
            que.push(i);
            cnt++;
        }
    }
    while(!que.empty())
    {
        int now=que.front();
        que.pop();
        for(int i=0;i<pic[now].size();i++)
        {
            int tmp=pic[now][i];
            degree[tmp]--;
            if(degree[tmp]==0)
            {
                vis[tmp]=1;
                cnt++;
                que.push(tmp);
            }
        }
    }
    return cnt+3<=n?1:0;
}
void dfs(int p,int s,int ps)
{
    //cout<<"p="<<p<<endl;
    if(p==ps&&s==3)
    {
        flag=1;
        return;
    }
    if(s>3)
        return;
    for(int i=0;i<pic[p].size();i++)
    {
        int t=pic[p][i];
        if(!vis[t])
            dfs(t,s+1,ps);
        if(flag)
            return;
    }
}
int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            pic[i].clear();
            degree[i]=0;
            vis[i]=0;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss+1);
            for(int j=1;j<=n;j++)
            {
                if(ss[j]=='1')
                {
                    pic[i].push_back(j);
                    degree[j]++;
                }
            }
        }
        printf("Case #%d: ",++cas);
        flag=0;
        if(solve(n))
        {
            for(int i=1;i<=n;i++)
            {
                if(!vis[i])
                {
                    dfs(i,0,i);
                    if(flag)
                        break;
                    vis[i]=1;
                }
            }
        }
        if(flag)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

其实可以不用这么麻烦。!_!
题目中有一句话:“scientists find that there is love between any of two people”
此题可以一遍拓扑排序判环求解 即只需要找到一个环,
就必定存在三元环
证明如下:
假设存在一个n元环,因为a->b有边,b->a必定没边,反之也成立
所以假设有环上三个相邻的点a-> b-> c,那么如果c->a间有边,
就已经形成了一个三元环,如果c->a没边,那么a->c肯定有边,
这样就形成了一个n-1元环。。。。
所以只需证明n大于3时一定有三元环即可,显然成立。

#include <bits/stdc++.h>
using namespace std;
const int N=2010;
vector<int>pic[N];
char ss[N];
bool vis[N];
int degree[N];
queue<int>que;
bool solve(int n)
{
    int cnt=0;
    while(!que.empty())
        que.pop();
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            vis[i]=1;
            que.push(i);
            cnt++;
        }
    }
    while(!que.empty())
    {
        int now=que.front();
        que.pop();
        for(int i=0;i<pic[now].size();i++)
        {
            int tmp=pic[now][i];
            degree[tmp]--;
            if(degree[tmp]==0)
            {
                vis[tmp]=1;
                cnt++;
                que.push(tmp);
            }
        }
    }
    return cnt==n?1:0;
}
int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            pic[i].clear();
            degree[i]=0;
            vis[i]=0;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss+1);
            for(int j=1;j<=n;j++)
            {
                if(ss[j]=='1')
                {
                    pic[i].push_back(j);
                    degree[j]++;
                }
            }
        }
        printf("Case #%d: ",++cas);
        if(!solve(n))
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

【4】Following Orders POJ - 1270
这个题目,不用拓扑排序的步骤,只根据概念就可以解决。类似输出全排列。
一直超时,最后发现是输入的问题。>_<!
AC代码:

#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
vector<int>pre[30];
char ss[1000];
int cnt,p[30];
bool vis[30],book[30];
void dfs(int n)
{
    if(n==cnt)
    {
        for(int i=0;i<cnt;i++)
            printf("%c",p[i]+'a');
        printf("\n");
        return;
    }
    for(int i=0;i<26;i++)
    {
       bool f=1;
       if(vis[i]||!book[i])
        continue;
       for(int j=0;j<pre[i].size();j++)
       {
           if(!vis[pre[i][j]])
                f=0;
       }
       if(f)
       {
            vis[i]=1;
            p[n]=i;
            dfs(n+1);
            vis[i]=0;
       }
   }
}
int main()
{
    char x,y,z;
    while(gets(ss))//tle
    {
        memset(book,0,sizeof(book));
        memset(vis,0,sizeof(vis));
        memset(p,0,sizeof(p));
        cnt=0;
        int len=strlen(ss);
        for(int i=0;i<len;i++)
        {
            if(ss[i]!=' ')
            {
                cnt++;
                book[ss[i]-'a']=1;
            }
        }
        for(int i=0;i<30;i++)
            pre[i].clear();
        while(scanf("%c %c%c",&x,&y,&z))
        {
            pre[y-'a'].push_back(x-'a');
            if(z=='\n')
                break;
        }
        dfs(0);
        printf("\n");
    }
    return 0;
}

tle代码:

#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
map<char,int>mp;
vector<int>pre[25];
char cc[25];
int cnt,p[30];
bool vis[25];
void dfs(int n)
{
    if(n==cnt)
    {
        for(int i=0;i<cnt;i++)
            printf("%c",cc[p[i]]);
        printf("\n");
        return;
    }
    for(int i=1;i<=cnt;i++)
    {
       bool f=1;
       if(vis[i])
        continue;
       for(int j=0;j<pre[i].size();j++)
       {
           if(!vis[pre[i][j]])
                f=0;
       }
       if(f)
       {
           vis[i]=1;
           p[n]=i;
           dfs(n+1);
            vis[i]=0;
       }
   }
}
int main()
{
    char x,y,z;
    while(scanf("%c%c",&x,&y)!=EOF)//tle
    {
        cnt=0;
        mp[x]=++cnt;
        cc[cnt]=x;
        while(scanf("%c%c",&x,&y))
        {
            mp[x]=++cnt;
            cc[cnt]=x;
            if(y=='\n')
                break;
        }
        memset(vis,0,sizeof(vis));
        for(int i=0;i<25;i++)
            pre[i].clear();
        while(scanf("%c %c%c",&x,&y,&z))
        {
            pre[mp[y]].push_back(mp[x]);
            if(z=='\n')
                break;
        }
        dfs(0);
        printf("\n");
    }
    return 0;
}

【5】Sorting It All Out POJ - 1094
【6】Window Pains POJ - 2585
【7】Cleaning Shifts POJ - 2376
【8】逃生 HDU - 4857
【9】Ponds HDU - 5438
【10】Paint the Grid Again ZOJ - 3780
待更新。。。