题目:http://acm.hdu.edu.cn/showproblem.php?pid=2647
题意是给n个人,m个x,y(x的钱要比y的钱多),每个人最少888,问最少要多少钱?
自己写老是想着dfs,结果dfs搜的头都晕了,还是不对。
应该是分层次的排,先排888,然后889,890。。。
先遍历找到所有入度为零且未标记的点,然后将这些点所连接的点的存一下,等遍历完,再将这些存的点的入度-1,这样就将这些点分成不同的层次,第一次为888,第二层为889,,,,,
还有就是判断环,如果是环的话,那么若入度为零且未标记的点的个数为零则说明为环。
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define printscanf freopen("intput.txt","r",stdin);
#define printprintf freopen("output.txt","w",stdout);
const int spot=10010;
const int edge=20010;
const int maxn=0;
const double pi=acos(-1.0);
int n,m,head[spot],sizes=0,sum[spot],ord[spot];
bool flag[spot];
struct stu
{
int to,next;
} a[edge];
void init()
{
memset(flag,0,sizeof(flag));
memset(sum,0,sizeof(sum));
memset(head,-1,sizeof(head));
sizes=0;
}
void add_edge(int x,int y)
{
a[sizes].to=y;
a[sizes].next=head[x];
head[x]=sizes++;
}
int tp_sort()
{
int ans=0,i,j,dep=0,k,v,length=0;
for(;;)
{
k=0;
for(i=1; i<=n; i++)
{
if(!flag[i]&&!sum[i]) //若入度为零且未标记
{
ans+=dep+888,length++,flag[i]=1; //dep表示第几层
for(j=head[i]; j+1; j=a[j].next)
{
v=a[j].to;
ord[++k]=v; //将与入度为零的点连接的点存起来
}
}
}
if(length==n) return ans;
if(!k) return -1; //若入度为零的点无,则说明有环的存在
for(i=1; i<=k; i++)
sum[ord[i]]--; //这些点入度-1
dep++; //层数+1
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
int x,y;
for(i=1; i<=m; i++)
{
scanf("%d%d",&x,&y); //建边是y->x
add_edge(y,x);
sum[x]++;
}
printf("%d\n",tp_sort());
}
}