jzoj医院【模拟】(水代码)

本文介绍了一种用于优化城市医院布局的算法,确保每个城市至少能被一家医院覆盖,同时考虑医院之间的距离,以减少市民的不满意度。通过设定入度为0的城市和路径大于等于3的城市为医院位置,实现最小化不满意度值之和。

>Description
一个城市至多只能有一间医院,同时,两个相邻的城市也只能有一间医院。注意城市i与城市j相邻当且仅当G中存在一条有向边<i,j>或<j,i>。其他城市没有医院的人:

S[i] = ( 离城市i最近的医院到城市i所经过的边数 / 3 ) * U

你要注意你的方案必须能让医院覆盖到所有的城市,即每个城市都至少有一个医院能出发到达。


>Input
输入第一行为两个整数N和M,分别表示城市数与边的数量。1<=N<=100,0<=M<=10000。

接下来M行,每行两个整数X和Y,1<=X,Y<=N,X≠Y,表示存在一条X到Y的有向边。

最后一行为一个整数U,为定义不满意度值中使用到的那个常数。

>Output
输出包含三行,第一行为你找到的最小的不满意度值之和,第二行为你的方案建立的医院数量H,第三行有H个整数,为建立医院所在的城市,按城市编号由小到大排序。这样的方案可能不唯一,在保证不满意度值之和最小的情况下,输出任意一种均可。


>Sample Input
4 3
2 1
4 3
3 2
10
>Sample Output
0
2
2 4


>解题思路
T_T水代码,bug值得你拥有。

巨大模拟。
把入度为0的直接设为医院,然后算路径,路径大于等于3的也直接设为医院。


>代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct ooo
{
	int to,next;
}a[10005]; //邻接表a储存每一个点可以到达的点(to)
struct oo
{
	int from,next;
}b[10005]; //邻接表b储存每一个点可以从那一些点过来(from)
int x,y,n,m,h[105],hh[105],u;
int lhq[105],c[105],t;
bool yd[105];
int main()
{
	memset(c,0x7f,sizeof(c));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		lhq[y]++; //lhq存入度
		a[i]=(ooo){y,h[x]}; h[x]=i;
		b[i]=(oo){x,hh[y]}; hh[y]=i; //邻接表们
	}
	scanf("%d",&u);
	printf("0\n"); //不管怎样都一定是0
	for(int i=1;i<=n;i++)
	  if(lhq[i]==0) //入度为0的设为医院
		{
			yd[i]=1; t++; c[i]=0; //依次:把i标记为医院,医院数t++,i的路径为0
			for(int j=h[i];j;j=a[j].next) //处理i所连接的点
			{
				c[a[j].to]=1; //路径为1
				if(yd[a[j].to]) t--; 
				yd[a[j].to]=0; //如果它(连接的点)以前为医院就不设它为医院
			}
		}
	for(int i=1;i<=n;i++)
	{
		if(c[i]==c[0]) //如果当前点没有存过路径
		{
		  for(int j=hh[i];j;j=b[j].next)
		   c[i]=min(c[i],c[b[j].from]+1); //循环它的所有起点,min算出最短路径
		  if(c[i]>=3)
		  {
		  	c[i]=0; t++; yd[i]=1; //如果路径大于等于3了就设为医院
		  }
		}
	}
	printf("%d\n",t);
	for(int i=1;i<=n;i++)
	 if(yd[i]) printf("%d ",i);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值