1. 程式人生 > >2018QBXT刷題遊記(6)

2018QBXT刷題遊記(6)

【2018QBXT刷題遊記】

Day1 TEST2

T3 network

在電腦科學中,經常要通過分析變數之間的相關性來簡化計算過程。變數
間的相關性可以用有向圖 G = V , E

G=( V,E) 來表示,圖中的點表示變數,邊表示變數間
的關係。這裡 G G 滿足: G G 中的所有邊都從編號小的點指向編號大的點。
從圖中選出一個點集 T
V T⊆V
,如果 T T 中的任意兩個點之間都有邊(方向是編
號小的點指向編號大的點),則稱 T
T
為團。特別地,空集也認為是一個團。
如果存在一個點,與 T T 中的任意一個點之間都有邊( 方向是編號小的點指
向編號大的點),那麼稱 T 為可擴團。
如果一個團 S S 不是可擴團,那麼稱它為極大團。
給出 G G ,求 G G 有多少個不同的極大團。
這裡 G G 滿足一個性質:對於 G G 中任意一個點 i i , 用 H [ i ] H[i] 表示編號比 i 小的點
中所有與 i 有邊相連的點的集合,那麼 H [ i ] H[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\n",ans);
	return 0;
}