用数组模拟邻接表 hdu2647

来源:互联网 发布:牵丝戏mmd动作数据 编辑:程序博客网 时间:2024/06/05 07:06

Reward

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 57   Accepted Submission(s) : 30

Font: Times New Roman | Verdana | Georgia

Font Size:  

Problem Description

Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.

Input

One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.

Output

For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.

Sample Input

2 11 22 21 22 1

Sample Output

1777

-1

   

这道题的数据量是10000*10000,经过我的试验,数据量为4000*4000时就会炸。因此这道题不可以用邻接矩阵的方法来保存图,而要采用邻接表的方法来保存图。邻接表的实现如果通过指针来实现就很烦,因此我们可以采用数组来模拟邻接表。

具体参考大神博客 点击打开链接

我们可以采用一个edge[MAX]的结构体组以及一个head[MAX]的数组来保存整张图

struct node{    int s;//保存每一条边的起始点    int e;//保存每一条边的终止点    int next;//保存每一条边的上一条边的编号}edge[20010];//保存每一条边,下标表示每一条边的编号int head[10010];//保存每一个顶点的起始边的编号

下面是操作过程

int n,m;int a,b;int main(){    while(cin>>n>>m)    {        memset(head,-1,sizeof(head));//把每个顶点的初始边编号初始为-1,也就是没有的意思(memset()只有在初始化-1,0时才会正确)       for(int i=1;i<=m;i++)       {           cin>>a>>b;           edge[i].s=a;           edge[i].e=b;           edge[i].next=head[a];//将next值设为起始点已有的边的编号。           head[a]=i;//将head值设为现在顶点的编号       }       for(int i=1;i<=n;i++)       {           int k=head[i];//以每一个点为起点开始遍历           while(k!=-1)           {               cout<<edge[k].s<<" "<<edge[k].e<<endl;               k=edge[k].next;//下一条边           }       }    }}

题目链接 点击打开链接

#include<iostream>#include<string.h>using namespace std;struct node{    int s;    int e;    int next;}edge[20010];int head[10010];int rudu[10010];int n,m;int a,b;int toposort(){    int money=888;//初始奖励    int ans=0;//最后奖励总和    int temp[10010];    int tol;    for(int i=0;i<n;i+=tol)    {        tol=0;//入度为0的点数        int j;        for(j=1;j<=n;j++)            if(rudu[j]==0)            {                temp[tol++]=j;                rudu[j]=-1;            }        if(tol==0) return -1;//没有找到就是形成了环,达不到要求        ans=ans+money*tol;money++; //这一次入度为0的点数 *  此层的要求奖励额        for(j=0;j<tol;j++)//可达边的删除        {            int t=head[temp[j]];               while(t!=-1)               {                   rudu[edge[t].e]--;                   t=edge[t].next;               }        }    }    return  ans;}int main(){    while(cin>>n>>m)    {        memset(head,-1,sizeof(head));        memset(rudu,0,sizeof(rudu));       for(int i=1;i<=m;i++)       {           cin>>a>>b;           edge[i].s=b;           edge[i].e=a;           edge[i].next=head[b];           head[b]=i;           rudu[a]++;       }       cout<<toposort()<<endl;    }    return 0;}