题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647
题意:英语太差,胡乱翻得。
老板想给n个员工发奖金(必要的资本安抚),为了不公平起见,他准备给每个员工不同的奖金,比如输入1 2,就表示1号员工要拿奖金要比2号员工多,多一块也是多,所以老板想问你怎么样才能发的钱最少???
Sample INput
2 1
1 2
2 2
1 2
2 1
Sample OUTput
1777
-1
思路:
好吧,10^4的点,开二维的就炸内存了,所以得用STL,坑爹的是要用vector,会有重复的边输入进去(我就纳闷了)。或者你可以自己创设一个以顶点为索引,起到和vector一样的作用。
简述下拓扑的步骤,找到入度为0的点,代表要最先出去的点,更新这个点或这些点的相邻可到点的入度,一般是减一。一直循环,直达所以点的入度为0,即都点被访问了。这题在于一下找到所以入度为零的点然后一起操作。
AC代码:
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std ;
const int N = 1e4+5;
int n,ans,m;
int main()
{
int x,y,cnt,rw ;
while( ~scanf("%d%d",&n,&m) )
{
ans = 0 ;
vector<int> a[N]; // 存放有向边,开二维就炸内存,即点a所能到达的所以顶点。
int in[N]={0},temp[N]={0}; // in记录每个点的入度,temp记录所有入度唯一的点。
while( m-- )
{
scanf("%d%d",&x,&y);
a[y].push_back(x);
in[x]++;
}
rw=888;
for(int i=1; i<=n; i+=cnt )
{
cnt=0;
for( int j=1; j<=n; j++ )
{
if( !in[j] )
{
temp[cnt++] = j ;
in[j] = -1 ;
}
} //找到所以入度为为0的点,cnt表示数量
if( !cnt ) { ans=-1; break ; } //没找到说明有环
ans += cnt*rw ; //计算
rw++;
for( int j=0; j<cnt; j++ ) //查找刚找到点的相邻可达到点,并使之-1
{
for( auto k : a[temp[j]] ) //自从用了auto遍历,妈妈再也不用担心我访问stl了
{
in[k]--;
}
}
}
printf("%d\n",ans);
}
return 0;
}
还有一份借鉴前人的代码:
#include <cstdio>
#include <cstring>
using namespace std ;
const int N = 1e4+5;
int n,m;
int in[N],temp[N];
struct NODE
{
int to,belong;
}e[N<<1];
int head[N]; // head[x] 表示已x为顶点,画出的边
void add( int x,int y,int cnt )
{
e[cnt].to = y ;
e[cnt].belong = head[x] ; //你懂了吗??? y belong -> x
head[x] = cnt; //连接 // 这步为拓展,因为以x为起点的边不止一条
}
//这几步起到了和vector数组一样的效果
int topo()
{
int cnt,rw=888,sum=0;
for( int i=0; i<n; i+=cnt )
{
cnt = 0;
for( int j=1; j<=n; j++ )
{
if( !in[j] )
{
in[j]=-1;
temp[cnt++] = j ;
}
}
if( !cnt ) return -1;
sum += cnt*rw; rw++;
for( int j=0; j<cnt; j++ )
{
for( int k=head[temp[j]] ; k!=-1; k=e[k].belong ) //遍历访问相邻可达顶点
{
in[ e[k].to ] -- ;
}
}
}
return sum ;
}
int main()
{
int x,y ;
while( ~scanf("%d%d",&n,&m) )
{
memset(in,0,sizeof(in));
memset(head,-1,sizeof(head));
for( int i=1; i<=m; i++ )
{
scanf("%d%d",&x,&y);
add(y,x,i);
in[x]++;
}
printf("%d\n",topo());
}
return 0;
}