hdu 2647 Reward
拓扑排序入门题,可以用STL来做,这份代码中没有用
对于给出的图判断是否为有向无环图(dag),若不是,输出-1
其实是按层来处理拓扑序列,算法是先找出入度为0的点,然后删除所有以这些顶点为弧尾的弧,使弧头的入度减1,然后再看下一轮的顶点中那些顶点入度为0,然后依此类推,直到所有点的入度都为0,如果最后结束的时候所有点入度为0,那么是一个dag,否则不是,输出-1,这个过程可以用队列来实现,这个代码里面没有这样做,而是每一层都重新扫描一遍,找出入度为0的顶点(之前已经纳入拓扑序列的顶点就用vis[i]=1来标记),应该用队列实现的话时间会更好
另外其中是要构建邻接表的,用数组来构建,当然可以直接用STL的vector来实现,队列也可以用STL的queue来实现,这份代码中都没有这样做
另外注意一点,输入中a b 有向边是b->a , 不要搞反了
#include <stdio.h> #include <string.h> #define MAXN 10010 #define MAXM 20010 int n,m; int first[MAXN],in[MAXN]; int u[MAXM],v[MAXM],next[MAXM]; bool vis[MAXN]; void input() { int i,a,b,f; memset(first,-1,sizeof(first)); memset(in,0,sizeof(in)); for(f=1,i=0; i<m; i++) { scanf("%d%d",&a,&b); u[i]=b; v[i]=a; in[v[i]]++; next[i]=first[u[i]]; first[u[i]]=i; } } int topsort() { int sum; int temp[MAXN]; int i,j,k,c,t; memset(vis,0,sizeof(vis)); c=0; sum=0; j=0; //j表示的是层数,第一层是0,所以工资为888,依次是889.890 //c表示已经有多少个点纳入拓扑序列,c=n则是dag //sum是最后的答案 while(1) { k=0; for(i=1; i<=n; i++) //对应n个顶点 if(!vis[i] && in[i]==0) { vis[i]=1; c++; sum+=(888+j); temp[k++]=i; //记录下当前这一轮找到的入度为0的顶点 } if(c>=n) return sum; if(!k) return -1; //如果在这次构建结束后,扫描所有顶点都找不到入度为0那说明存在环 for(i=0; i<k; i++) //对应temp数组,这一轮找到的入度为0的顶点,要遍历它的邻接表,使对应的弧头入度减1 { t=temp[i]; //记录弧尾顶点标号 t=first[t]; //记录这个顶点的第一条弧的编号 while(t!=-1) { in[v[t]]--; t=next[t]; } } j++; } } int main() { int ans; while(scanf("%d%d",&n,&m)!=EOF) { input(); printf("%d\n",ans=topsort()); } return 0; }