2415. Cowntact Tracing

2415. Cowntact Tracing

(File IO): input:tracing.in output:tracing.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet


题目描述

由于高传染性的牛传染病 COWVID-19 的爆发,Farmer John 非常担忧他的奶牛们(编号为 1…N)的健康。最近,Farmer John 对他的所有奶牛进行了检测,发现有一部分奶牛对该疾病的检测结果呈阳性。利用牛棚内的视频监控,他得以查看最近的奶牛之间的互动行为,结果发现奶牛们互相打招呼时,她们会握蹄,不幸的是这是一种会将疾病从一头奶牛传播给另一头奶牛的行为。Farmer John 汇总了一个添加了时间戳的清单,每条数据的形式为 (t,x,y),表示在时间 t,奶牛 x 与奶牛 y 握了蹄。Farmer John 同时还知道以下信息:
(一)他的农场上恰有一头奶牛最初带有携带疾病(我们将这头奶牛称为“零号病人”)。
(二)一旦一头奶牛被感染,她会在接下来的 K 次握蹄中传染疾病(可能会与同一头奶牛握蹄多次)。握蹄 K 次后,她不再在此后的握蹄中传染疾病(因为此时她意识到了她会传染疾病,于是会仔细地洗蹄)。
(三)一旦一头奶牛被感染,她会持续处于被感染状态。
不幸的是,Farmer John 不知道他的 N 头奶牛中的哪一头是零号病人,也不知道 K 的值!基于他的数据,请帮助他缩小这些未知量的范围。保证至少有一种可能的情况。

输入

输入的第一行包含 N(2≤N≤100)和 T(1≤T≤250)。下一行包含一个长为 N 的字符串,每个字符均为 0 或 1,表述目前 Farmer John 的 N 头奶牛的状态——0 表示一头健康的奶牛,1 表示一头染病的奶牛。以下 T 行每行包含 Farmer John 的互动清单中的一条记录,由三个整数 t、x 和 y组成,其中 t 为一次互动发生的正整数时间(t≤250),x 和 y 为范围 1…N 内的不同整数,表示时间 t 握蹄的两头奶牛。在每一时刻至多只有一次互动发生。

输出

输出一行,包含三个整数 x、y 和 z,其中 x 为可能为零号病人的奶牛数量,y 为与数据一致的最小可能 K 值,z 为与数据一致的最大可能 K 值(如果通过数据无法推断 K 的上界,z 输出 “Infinity”)。注意可能有 K=0。

样例输入

4 3
1100
7 1 2
5 2 3
6 2 4

样例输出

1 1 Infinity

提示

唯一可能是零号病人的是奶牛 1。对于所有的 K>0,奶牛 1 在时刻 7 感染奶牛 2,而奶牛 3 和奶牛 4 均不会被感染。

头皮都抓破,历时48小时无眠后,终于…
别光看,记得点赞!

题目思路:
1.将握蹄的数据先按照时间做升序排序
2.枚举任意一头牛;(统计零号病人数量)

3.算出k的上下界(后面详解)
我做了个超赞的剪枝没病的牛就不可能是零号病人 !(如果数据中只有少数牛是病牛,那么优化是显著的)

如何算k的上下界

用l表示下界,r为上界;
用g数组记录以第i头牛为零号病人,握蹄k次后,牛的感染情况;
求下界:
我们用一层循环来模拟k的变化;(for int k=0~T)
根据题意,每一头牛都只能在握蹄K次内感染another,所以我们需用一个数组wt来记录已握蹄次数。

void qxj(int i) //求下界 
{
	for(int k=0;k<=T;k++)
	{
		memset(wt,0,sizeof(wt));
		memset(g,0,sizeof(g));
		g[i]=1; //零号病人 
		for(int j=1;j<=T;j++)
		{
			if(g[a[j].x]&&!g[a[j].y]&&wt[a[j].x]<k)      wt[a[j].x]++,g[a[j].y]=1; //x感染y
			else if(g[a[j].y]&&!g[a[j].x]&&wt[a[j].y]<k) wt[a[j].y]++,g[a[j].x]=1; //y感染x
			else if(g[a[j].x]&&g[a[j].y])                wt[a[j].x]++,wt[a[j].y]++; //两牛都已感染 
		}
		//cout<<check()<<endl;
		if(check()) 
		{
			flag=1; l=min(l,k); return; //符合他是零号病人,记录k的下界 
		}
	}
}

求上界:
同理,但是有个条件,没下界就没上界(因为他不可能是零号病人)
那如何判断"Infinity"的情况呢?
so easy,如果第T次都符合,显然T-1,T-2……也符合,当然我们讲得是握蹄,不是吃饭!,所以上界无法判断(Infinity)
能求出一个小于T的值,那显然是上界(我是倒序的)
当然你也可以升序,只不过要取max!

void qsj(int i)  //求上界 
{
	if(!flag) return;
	for(int k=T;k>=0;k--)
	{
		memset(wt,0,sizeof(wt));
		memset(g,0,sizeof(g));
		g[i]=1; //零号病人 
		for(int j=1;j<=T;j++)
		{
			if(g[a[j].x]&&!g[a[j].y]&&wt[a[j].x]<k)      wt[a[j].x]++,g[a[j].y]=1; //x感染y
			else if(g[a[j].y]&&!g[a[j].x]&&wt[a[j].y]<k) wt[a[j].y]++,g[a[j].x]=1; //y感染x
			else if(g[a[j].x]&&g[a[j].y])                wt[a[j].x]++,wt[a[j].y]++; //两牛都已感染 
		}
		//cout<<check()<<endl;
		if(check()) 
		{
			r=max(r,k); return; //符合他是零号病人,记录k的上界 	
		}
	}
}

AC code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
struct node
{
	int t,x,y;
} a[300];
int n,T,f[210],g[210],wt[210],l=MAX,r,tot;
bool flag;
string s;
bool cmp(node x,node y) {return x.t<y.t;}
void input()
{
	scanf("%d%d",&n,&T);
	cin>>s;
	for(int i=0;i<n;i++) if(s[i]=='1') f[i+1]=1;
	for(int i=1;i<=T;i++) scanf("%d%d%d",&a[i].t,&a[i].x,&a[i].y);
	sort(a+1,a+1+T,cmp);
}
bool check()
{
	for(int i=1;i<=n;i++) if(f[i]!=g[i]) return 0;	
	return 1; 
}
void qxj(int i) //求下界 
{
	for(int k=0;k<=T;k++)
	{
		memset(wt,0,sizeof(wt));
		memset(g,0,sizeof(g));
		g[i]=1; //零号病人 
		for(int j=1;j<=T;j++)
		{
			if(g[a[j].x]&&!g[a[j].y]&&wt[a[j].x]<k)      wt[a[j].x]++,g[a[j].y]=1; //x感染y
			else if(g[a[j].y]&&!g[a[j].x]&&wt[a[j].y]<k) wt[a[j].y]++,g[a[j].x]=1; //y感染x
			else if(g[a[j].x]&&g[a[j].y])                wt[a[j].x]++,wt[a[j].y]++; //两牛都已感染 
		}
		//cout<<check()<<endl;
		if(check()) 
		{
			flag=1; l=min(l,k); return; //符合他是零号病人,记录k的下界 
		}
	}
}
void qsj(int i)  //求上界 
{
	if(!flag) return;
	for(int k=T;k>=0;k--)
	{
		memset(wt,0,sizeof(wt));
		memset(g,0,sizeof(g));
		g[i]=1; //零号病人 
		for(int j=1;j<=T;j++)
		{
			if(g[a[j].x]&&!g[a[j].y]&&wt[a[j].x]<k)      wt[a[j].x]++,g[a[j].y]=1; //x感染y
			else if(g[a[j].y]&&!g[a[j].x]&&wt[a[j].y]<k) wt[a[j].y]++,g[a[j].x]=1; //y感染x
			else if(g[a[j].x]&&g[a[j].y])                wt[a[j].x]++,wt[a[j].y]++; //两牛都已感染 
		}
		//cout<<check()<<endl;
		if(check()) 
		{
			r=max(r,k); return; //符合他是零号病人,记录k的上界 	
		}
	}
}
void work()
{
	for(int i=1;i<=n;i++)
	{
		flag=0;
		if(!f[i]) continue;  //没病的牛就不可能是零号病人 
		qxj(i);
		qsj(i);
		if(flag) tot++;//符合条件,零号病人加一 	
	}
}
int main()
{
	//fre(tracing);
	input();
	work();
	printf("%d %d ",tot,l);
	if(r==T) printf("Infinity");
	else printf("%d",r); 
	return 0;
}
发布了130 篇原创文章 · 获赞 93 · 访问量 6799

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/105455819
今日推荐