hdu 2647 Reward ( 拓扑排序 )

来源:互联网 发布:淘宝上怎么找卖bt种子 编辑:程序博客网 时间:2024/04/23 23:09

统计各结点出度,出度为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 10005using 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);}