hdu 2647 Reward ( 拓撲排序 )

統計各結點出度,出度爲0的點表示他們(A類)所需的reward爲888,而reward要比他們多的(B類)則爲888+1,reward要比B類多的(C類)則爲888+2.。。。

其中若一開始從A類得到了B類,然後有某個B類要比另一個B類的reward多,則該B類的reward從888+1改爲888+2.。。。

以此類推,採用逆向拓撲排序可解此題

 

 

#include <cstdio>
#include <cstring>
#include <vector>
#define MAX 10005
using namespace std;
vector <int> map[MAX];
int out[MAX],cnt,vis[MAX],add[MAX];

void update(int v,int a)
{
    if(!vis[v])
    cnt++;
    vis[v]=1;
    for(unsigned i=0;i<map[v].size();i++)
    {
        if(a>add[map[v][i]])
        add[map[v][i]]=a;
        update(map[v][i],a+1);
    }
}

bool repeat(int u,int v)
{
    for(unsigned i=0;i<map[v].size();i++)
    if(map[v][i]==u)
    return true;
    return false;
}

void solve(int n,int m)
{
    for(int i=1;i<=n;i++)
    map[i].clear();
    memset(out,0,sizeof(out));
    memset(vis,0,sizeof(vis));
    int u,v;
   for(int i=0;i<m;i++)
   {
       scanf("%d%d",&u,&v);
       if(!repeat(u,v))
       {
           map[v].push_back(u);
           out[u]++;
       }
   }
   cnt=0;
   memset(add,0,sizeof(add));

   for(int i=1;i<=n;i++)
   if(!out[i])
   update(i,1);

   if(cnt==n)
   {
       int res=0;
       for(int i=1;i<=n;i++)
       res+=add[i];
       printf("%d\n",res+n*888);
   }
   else
   printf("-1\n");
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)>0)
        solve(n,m);
}

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章