Loading

3205. 【HNOI模拟题】Dual-SIM Phone

Description

彼得,一个学生,想要从短信业务中获利。当然,他也想花最少的钱发送信息,并且尽快地发送信息。因此,他想买一个双卡手机,对于两个运营商的卡可以同时工作。现在,彼得可以发送短信给某个电话号码,通过两个运营商中花钱更少的一个。

不幸的是,并非所有手机运营商可以通过他们发送短信给其他运营商的电话号码。帮助彼得选择一对运营商,使得他能够发送短信给所有运营商的电话号码,而且发送短信的最大费用最小。

Solution

考虑直接暴力。

暴力枚举两个点,然后暴力判断这两个点是否连向了所有点,求出最小的最大花费,更新答案。

时间复杂度看上去 \(O(MN^2)\),但是跑不满。

另外可以加优化,判断 两个点有没有没有出度 的和 两个点出度之和 是否大于 \(n\)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define M 100005
#define inf 2147483647
using namespace std;
struct node
{
	int x,y,z;
}a[M],c[M];
int n,m,x,y,z,ans,tot,st[N],out[N];
bool cmp(node x,node y)
{
	if (x.x<y.x) return true;
	if (x.x>y.x) return false;
	return x.y<y.y;	
}
void get(int x,int y)
{
	int i=st[x],j=st[y];
	tot=0;
	memset(c,0,sizeof(c));
	while (i<=m&&j<=m&&a[i].x==x&&a[j].x==y)
	{
		if (a[i].y<=a[j].y) c[++tot]=a[i++];
		else c[++tot]=a[j++];
	}
	while (i<=m&&a[i].x==x) c[++tot]=a[i++];
	while (j<=m&&a[j].x==y) c[++tot]=a[j++];
}
int solve(int x,int y)
{
	if (out[x]+out[y]<n) return inf;
	if (st[x]==-1||st[y]==-1) return inf;
	get(x,y);
	int res=0,num=0;
	for (int i=2;i<=tot+1;++i)
	{
		if (i==tot+1||c[i].y!=c[i-1].y)
		{
			res=max(res,c[i-1].z);
			++num;
		}
		else c[i].z=min(c[i].z,c[i-1].z);
		if (res>ans) break;
	}
	if (num<n) return inf;
	else return res;
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;++i)
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),++out[a[i].x];
	sort(a+1,a+m+1,cmp);
	memset(st,-1,sizeof(st));
	st[a[1].x]=1;
	for (int i=2;i<=m;++i)
		if (a[i].x!=a[i-1].x) st[a[i].x]=i;
	ans=inf;
	for (int i=1;i<n;++i)
		for (int j=i+1;j<=n;++j)
			ans=min(ans,solve(i,j));
	if (ans==inf) printf("No solution\n");
	else printf("%d\n",ans);
	return 0;
}
posted @ 2021-10-05 20:06  Thunder_S  阅读(52)  评论(0)    收藏  举报