【2018QBXT刷题游记】
Day1 TEST2
T3 network
在计算机科学中,经常要通过分析变量之间的相关性来简化计算过程。变量
间的相关性可以用有向图 来表示,图中的点表示变量,边表示变量间
的关系。这里 满足: 中的所有边都从编号小的点指向编号大的点。
从图中选出一个点集 ,如果 中的任意两个点之间都有边(方向是编
号小的点指向编号大的点),则称 为团。特别地,空集也认为是一个团。
如果存在一个点,与 中的任意一个点之间都有边( 方向是编号小的点指
向编号大的点),那么称 T 为可扩团。
如果一个团 不是可扩团,那么称它为极大团。
给出 ,求 有多少个不同的极大团。
这里 满足一个性质:对于 中任意一个点 , 用 表示编号比 i 小的点
中所有与 i 有边相连的点的集合,那么 是一个团。
【分析】这题好水啊……orz
根据提供的性质,只需要按照从大到小的顺序判断每一个点i
若与它相连的最大点j的入度比当前点小
那么以j为最大点的团一定是可扩团,i就是可扩点(还可能有更多)
注意重边的判断。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char c;int n,m,cnt,ans;int read(){c=getchar();int f=1,s=0;
while(c<'0'||c>'9')if(c=='-')f=-1,c=getchar();
while(c>='0'&&c<='9')s=s*10+c-'0',c=getchar();return f*s;}
struct Edge{
int a,b;
}E[1000007];
int tot[1000007],last[1000007];bool qwq[1000007];
bool cmp(Edge x,Edge y){
if(x.a!=y.a)return (x.a<y.a);
else return (x.b<y.b);
}
int main(){
freopen("network.in","r",stdin);
freopen("network.out","w",stdout);
n=read();m=read();
for(int i=1;i<=m;i++){
E[i].a=read();E[i].b=read();
}cnt=0;
sort(E+1,E+1+m,cmp);
for(int i=1;i<=m;i++){
cnt++;
E[cnt]=E[i];
while(i<m && E[i].a==E[i+1].a &&E[i].b==E[i+1].b)i++;
}m=cnt;
for(int i=1;i<=m;i++){
tot[E[i].b]++;
last[E[i].b]=max(E[i].a,last[E[i].b]);
}ans=0;
for(int i=n;i>=1;i--){
if(last[i] && tot[i]>tot[last[i]])qwq[last[i]]=1;
if(!qwq[i])ans++;
}
printf("%d
",ans);
return 0;
}