当前位置: 代码迷 >> 综合 >> 用数组模拟邻接表 hdu2647
  详细解决方案

用数组模拟邻接表 hdu2647

热度:60   发布时间:2023-11-18 03:46:10.0

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 1
1 2
2 2
1 2
2 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;
}