【JZOJ】医院

医院

n n n个点和 m m m条边的有向图和一个常数 k k k,在某几个点设置医院,相邻的两个点不能一起设置医院,某一个点的值为: ( 他 离 最 近 的 医 院 的 距 离 / 3 ) ∗ k (他离最近的医院的距离/3)*k /3k
输出所有点最小的和,并输出设了多少个医院,和医院设在哪一个点。
(有一个特别强的地方,医院数量不限,所以输出哪一个方案都行)

样例输入
4 3
2 1
4 3
3 2
10
样例输出
0
2
2 4
or
0
2
1 4

前言

这道题也点划水…
一个骗分直接拿50分

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
	printf("0\n1\n1");
	fclose(stdin);
	fclose(stdout);
	return 0;
}

听着巨佬讲课,好蒙啊

思路

“特别”复杂
有一个特别划水
就是因为题目描述,所以最小的值都是 0 0 0
S o So So常数 k k k没有任何用处,可以不用读
但是!
下面的并不是正解,到现在为止,暂时还没有哪一位 d a l a o dalao dalaoA了这一道题
但是!
只要能在题库中A了就行,如果有时间的话我会去请教一下其他 d a l a o dalao dalao

见code

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct whw
{
	int w,h;
}a[20025],b[20025];
int link[20025],h[20025],hw[20025],ht[20025];
bool ls[20025];
int n,m,k,x,y;
int main()
{
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
	memset(link,0x7f,sizeof(link));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&x,&y);
		h[y]++;//找一个入度为零的节点(根节点)(但有些图是环)
		a[i]=(whw){y,hw[x]};hw[x]=i;
		b[i]=(whw){x,ht[y]};ht[y]=i;//邻接表
	}
	scanf("%d",&k);//给他个面子,读入一下
	k=0;//记得清零
	for(int i=1;i<=n;++i)
		if(!h[i])
		{
			++k;//根节点设置一个医院
			ls[i]=1;//这一个点设置医院
			link[i]=0;//i到i为0
			for(int j=hw[i];j;j=a[j].h)
				link[a[j].w]=1;//将根节点算连接的点的距离赋值为1
		}
	for(int i=1;i<=n;++i)
		if(link[i]==link[0])//如果不是根节点
		{
			for(int j=ht[i];j;j=b[j].h)
				link[i]=min(link[i],link[b[j].w]+1);//最短路
			if(link[i]>=3)//如果值大于了0,就在此节点设置一个医院
			{
				link[i]=0;//在i点设置一个医院,所以值为0
				k++;//设置的医院数量+1
				ls[i]=1;//在此设置一个医院
			}
		}
	printf("0\n%d\n",k);//点值的和直接为0
	for(int i=1;i<=n;++i)
		if(ls[i])printf("%d ",i);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值