题目大意:比较搞笑,就是一头牛仰慕另一头牛,也可能会仰慕别的一堆牛。问你是不是会有那么几个牛,是除了他之外别的牛都仰慕的。求出这样的牛的个数。
构图,发现按问题性质,如果有一堆牛互相仰慕的,别且这堆牛被这一堆之外的牛都仰慕,很明显这堆牛就是解的一部分,抽象出来就是原图的极大连通子图可以收缩为一个点处理,最后在有向无环图上求出是否有某个点的可达性为n-1,那么这个点映射到原图上的点集的点个数即为所求。
注意如果新图是由一个以上不相交子图的并构成,那么解必为0。(其实大家都注意了就我没注意。。。)
解法: 构图,标记强分量,枚举边构造缩点新图,新图中枚举深搜起点,判断可达性。
关于性能,点多边少,可以选择邻接表存放,使用STL的set结构可以将判重边的时间降到logn。
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<string.h>
4
5
#define MAXV 100000
6
int postR[MAXV],post[MAXV];
7
int cnt0,cnt1;
8
9
typedef struct LinkNod *Link;
10
struct LinkNod
{
11
int dest;
12
Link next;
13
};
14
15
typedef struct GraphNod *Graph;
16
struct GraphNod
{
17
Link v[MAXV];
18
int vnum;
19
int id[MAXV]; // 分量标号
20
int hash[MAXV]; // 保存缩点数
21
};
22
Graph G,GR,Gch;
23
24
int visit[MAXV];
25
bool have,star;
26
int chNum,visiNum;
27
int degree[MAXV];
28
29
void DFS_1(Graph g,int w);
30
void DFS_bui(Graph g,Graph ch);
31
void DFS_ans(Graph g,int w);
32
33
int main()
{
34
int i,j,k;
35
int a,b;
36
int n,m;
37
int id;
38
Link pos,tmpPos;
39
40
G = (Graph)malloc(sizeof(struct GraphNod));
41
GR = (Graph)malloc(sizeof(struct GraphNod));
42
Gch = (Graph)malloc(sizeof(struct GraphNod));
43
while(scanf("%d%d",&n,&m)!=EOF)
{
44
G->vnum = GR->vnum = Gch->vnum = n;
45
memset(G,0,sizeof(int)*(n+1));
46
memset(GR,0,sizeof(int)*(n+1));
47
memset(Gch,0,sizeof(int)*(n+1));
48
for(i=0;i<m;i++)
{
49
scanf("%d%d",&a,&b); a--; b--;
50
// 原图
51
pos=G->v[b];
52
pos = (Link)malloc(sizeof(struct LinkNod));
53
pos->dest =a; pos->next=G->v[b];
54
G->v[b]=pos;
55
// 逆图
56
pos=GR->v[a];
57
pos = (Link)malloc(sizeof(struct LinkNod));
58
pos->dest =b; pos->next=GR->v[a];
59
GR->v[a]=pos;
60
}
61
memset(G->id,-1,sizeof(int)*(G->vnum+1));
62
memset(GR->id,-1,sizeof(int)*(GR->vnum+1));
63
memset(Gch->id,-1,sizeof(int)*(Gch->vnum+1));
64
memset(G->hash,0,sizeof(int)*(G->vnum+1));
65
memset(GR->hash,0,sizeof(int)*(GR->vnum+1));
66
memset(Gch->hash,0,sizeof(int)*(Gch->vnum+1));
67
cnt1=cnt0=0;
68
69
for(i=0;i<GR->vnum;i++)
70
if( GR->id[i]==-1 ) DFS_1(GR,i);
71
72
73
for(i=0;i<cnt0;i++)
{ postR[i] = post[i];}
74
75
for(cnt1=0,i=cnt0-1;i>-1;i--)
76
if(G->id[postR[i]]==-1)
{ DFS_1(G,postR[i]); cnt1++; }
77
78
Gch->vnum=cnt1;
79
memset(degree,0,sizeof(int)*(Gch->vnum));
80
DFS_bui(G,Gch);
81
82
star=false;
83
for(i=Gch->vnum-1;i>-1;i--) if(degree[i]==0)
{
84
visiNum=0; memset(visit,0,sizeof(int)*(Gch->vnum));
85
DFS_ans(Gch,i);
86
if( visiNum == Gch->vnum )
{ printf("%d\n",G->hash[i]); star=true; break; }
87
}
88
if( star == false ) printf("0\n");
89
90
}
91
return 0;
92
}
93
94
void DFS_1(Graph g,int w)
{
95
g->id[w] = cnt1; g->hash[cnt1]++; //printf("%d点染色为 %d\n",w+1,cnt1);
96
for( Link pos = g->v[w]; pos!=NULL; pos=pos->next ) if( g->id[ pos->dest ] == -1 ) DFS_1(g,pos->dest);
97
post[cnt0++] = w; // 后序编码
98
}
99
100
void DFS_ans(Graph g,int w)
{
101
visiNum++; visit[w]=1;
102
for( Link pos = g->v[w]; pos!=NULL; pos=pos->next ) if( !visit[pos->dest] )
{ DFS_ans(g,pos->dest); }
103
return ;
104
}
105
106
void DFS_bui(Graph g,Graph ch)
{
107
Link pos,pos2,tmp;
108
int i;
109
for(i=0;i<g->vnum;i++)
110
for(pos=g->v[i];pos;pos=pos->next)
{
111
if( g->id[i] != g->id[pos->dest] )
{
112
pos2=ch->v[ g->id[i] ]; have=0;
113
while(pos2)
{
114
if( pos2->dest == g->id[ pos->dest ] )
{ have=1; break; }
115
pos2=pos2->next;
116
}
117
if( have ==0 )
{
118
tmp = (Link)malloc(sizeof(struct LinkNod));
119
tmp->dest = g->id[ pos->dest ]; tmp->next = ch->v[ g->id[i] ];
120
ch->v[ g->id[i] ] = tmp;
121
degree[ g->id[ pos->dest ]]++;
122
}
123
}
124
}
125
return ;
126
}